home *** CD-ROM | disk | FTP | other *** search
/ Floppyshop 2 / Floppyshop - 2.zip / Floppyshop - 2.iso / diskmags / 0022-3.564 / dmg-0129 / general / xscheme.doc < prev   
Text File  |  1997-04-16  |  175KB  |  6,772 lines

  1.                        XSCHEME: An Object-oriented Scheme
  2.  
  3.                                   Version 0.17
  4.  
  5.                     (not yet updated for version 0.22 (BCB))
  6.  
  7.                                  March 2, 1989
  8.  
  9.  
  10.                                        by
  11.                                David Michael Betz
  12.                                   P.O. Box 144
  13.                              Peterborough, NH 03458
  14.  
  15.                              (603) 924-4145 (home)
  16.  
  17.                    Copyright (c) 1989, by David Michael Betz
  18.                               All Rights Reserved
  19.            Permission is granted for unrestricted non-commercial use
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.         XSCHEME                TABLE OF CONTENTS                  Page 2
  67.  
  68.  
  69.         TABLE OF CONTENTS
  70.  
  71.             TABLE OF CONTENTS..................................2
  72.             INTRODUCTION.......................................3
  73.             A NOTE FROM THE AUTHOR.............................4
  74.             EXPRESSIONS........................................5
  75.             BINDING FORMS.....................................10
  76.             SEQUENCING........................................11
  77.             DELAYED EVALUATION................................12
  78.             ITERATION.........................................13
  79.             DEFINITIONS.......................................14
  80.             LIST FUNCTIONS....................................15
  81.             DESTRUCTIVE LIST FUNCTIONS........................17
  82.             SYMBOL FUNCTIONS..................................18
  83.             VECTOR FUNCTIONS..................................19
  84.             ARRAY FUNCTIONS...................................20
  85.             CONVERSION FUNCTIONS..............................21
  86.             TYPE PREDICATES...................................22
  87.             EQUALITY PREDICATES...............................25
  88.             ARITHMETIC FUNCTIONS..............................26
  89.             NUMERIC COMPARISON FUNCTIONS......................29
  90.             BITWISE LOGICAL FUNCTIONS.........................30
  91.             STRING FUNCTIONS..................................31
  92.             STRING COMPARISON FUNCTIONS.......................32
  93.             CHARACTER COMPARISON FUNCTIONS....................33
  94.             INPUT/OUTPUT FUNCTIONS............................34
  95.             OUTPUT CONTROL FUNCTIONS..........................36
  96.             FILE I/O FUNCTIONS................................37
  97.             CONTROL FEATURES..................................39
  98.             ENVIRONMENT FUNCTIONS.............................40
  99.             UTILITY FUNCTIONS.................................41
  100.             SYSTEM FUNCTIONS..................................42
  101.             OBJECT REPRESENTATIONS............................43
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.         XSCHEME                   INTRODUCTION                    Page 3
  133.  
  134.  
  135.         XScheme is an implementation of the Scheme programming language
  136.         with extensions to support object-oriented programming.
  137.  
  138.         There are currently implementations of XScheme running on the
  139.         IBM-PC and clones under MS-DOS, on the Macintosh, the Atari-ST
  140.         and the Amiga.  It is completely written in the programming
  141.         language 'C' and is easily extended with user written built-in
  142.         functions and classes.  It is available in source form to non-
  143.         commercial users.
  144.  
  145.         This document is a brief description of XScheme.  XScheme
  146.         follows the "Revised^3 Report on the Algorithmic Language
  147.         Scheme".  It assumes some knowledge of Scheme or LISP and some
  148.         understanding of the concepts of object-oriented programming.
  149.  
  150.         I recommend the book "Structure and Interpretation of Computer
  151.         Programs" by Harold Abelson and Gerald Jay Sussman and published
  152.         by The MIT Press and the McGraw-Hill Book Company for learning
  153.         Scheme (and programming in general).  You might also find "The
  154.         Scheme Programming Language" by R. Kent Dybvig and "The Little
  155.         Lisper" by Daniel P. Friedman and Matthias Felleisen to be
  156.         helpful.
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.         XSCHEME              A NOTE FROM THE AUTHOR               Page 4
  199.  
  200.  
  201.         A NOTE FROM THE AUTHOR
  202.  
  203.         If you have any problems with XScheme, feel free to contact me
  204.         for help or advice.  Please remember that since XScheme is
  205.         available in source form in a high level language, many users
  206.         have been making versions available on a variety of machines.
  207.         If you call to report a problem with a specific version, I may
  208.         not be able to help you if that version runs on a machine to
  209.         which I don't have access.  Please have the version number of
  210.         the version that you are running readily accessible before
  211.         calling me.
  212.  
  213.         If you find a bug in XScheme, first try to fix the bug yourself
  214.         using the source code provided.  If you are successful in fixing
  215.         the bug, send the bug report along with the fix to me.  If you
  216.         don't have access to a C compiler or are unable to fix a bug,
  217.         please send the bug report to me and I'll try to fix it.
  218.  
  219.         Any suggestions for improvements will be welcomed.  Feel free to
  220.         extend the language in whatever way suits your needs.  However,
  221.         PLEASE DO NOT RELEASE ENHANCED VERSIONS WITHOUT CHECKING WITH ME
  222.         FIRST!!  I would like to be the clearing house for new features
  223.         added to XScheme.  If you want to add features for your own
  224.         personal use, go ahead.  But, if you want to distribute your
  225.         enhanced version, contact me first.
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.         XSCHEME                   EXPRESSIONS                     Page 5
  265.  
  266.  
  267.         EXPRESSIONS
  268.  
  269.         <variable>
  270.  
  271.             An expression consisting of a variable is a variable
  272.             reference.  The value of the variable reference is the value
  273.             stored in the location to which the variable is bound.  It
  274.             is an error to reference an unbound variable.
  275.  
  276.         (QUOTE <datum>)
  277.         '<datum>
  278.  
  279.             (quote <datum>) evaluates to <datum>.  <Datum> may be any
  280.             external representation of a Scheme object.  This notation
  281.             is used to include literal constants in Scheme code.  (quote
  282.             <datum>) may be abbreviated as '<datum>.  The two notations
  283.             are equivalent in all respects.
  284.  
  285.         <constant>
  286.  
  287.             Numeric constants, string constants, character constants,
  288.             and boolean constants evaluate "to themselves"; they need
  289.             not be quoted.
  290.  
  291.         (<operator> <operand>...)
  292.  
  293.             A procedure call is written by simply enclosing in
  294.             parentheses expressions for the procedure to be called and
  295.             the arguments to be passed to it.  The operator and operand
  296.             expressions are evaluated and the resulting procedure is
  297.             passed the resulting arguments.
  298.  
  299.         (<object> <selector> <operand>...)
  300.  
  301.             A message sending form is written by enclosing in
  302.             parentheses expressions for the receiving object, the
  303.             message selector, and the arguments to be passed to the
  304.             method.  The receiver, selector, and argument expressions
  305.             are evaluated, the message selector is used to select an
  306.             appropriate method to handle the message, and the resulting
  307.             method is passed the resulting arguments.
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.         XSCHEME                   EXPRESSIONS                     Page 6
  331.  
  332.  
  333.         (LAMBDA <formals> <body>)
  334.  
  335.             <Formals> should be a formal argument list as described
  336.             below, and <body>  should be a sequence of one or more
  337.             expressions.  A lambda expression evaluates to a procedure.
  338.             The environment in effect when the lambda expression is
  339.             evaluated is remembered as part of the procedure.  When the
  340.             procedure is later called with some actual arguments, the
  341.             environment in which the lambda expression was evaluated
  342.             will be extended by binding the variables in the formal
  343.             argument list to fresh locations, the corresponding actual
  344.             argument values will be stored in those locations, and the
  345.             expressions in the body of the lambda expression will be
  346.             evaluated sequentially in the extended environment.  The
  347.             result of the last expression in the body will be returned
  348.             as the result of the procedure call.
  349.  
  350.             <Formals> should have the following form:
  351.  
  352.                 (<var>... [#!OPTIONAL <ovar>...] [. <rvar>])
  353.               or
  354.                 (<var>... [#!OPTIONAL <ovar>...] [#!REST <rvar>])
  355.  
  356.               where:
  357.  
  358.                 <var>    is a required argument
  359.                 <ovar>   is an optional argument
  360.                 <rvar>   is a "rest" argument
  361.  
  362.             There are three parts to a <formals> list.  The first lists
  363.             the required arguments of the procedure.  All calls to the
  364.             procedure must supply values for each of the required
  365.             arguments.  The second part lists the optional arguments of
  366.             the procedure.  An optional argument may be supplied in a
  367.             call or omitted.  If it is omitted, a special value is given
  368.             to the argument that satisfies the default-object?
  369.             predicate.  This provides a way to test to see if an
  370.             optional argument was provided in a call or omitted.  The
  371.             last part of the <formals> list gives the "rest" argument.
  372.             This argument will be bound to the rest of the list of
  373.             arguments supplied to a call after the required and optional
  374.             arguments have been removed.
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.         XSCHEME                   EXPRESSIONS                     Page 7
  397.  
  398.  
  399.         (IF <test> <consequent> [<alternate>])
  400.  
  401.             An if expression is evaluated as follows:  first, <test> is
  402.             evaluated.  If it yields a true value, then <consequent> is
  403.             evaluated and its value is returned.  Otherwise, <alternate>
  404.             is evaluated and its value is returned.  If <test> yields a
  405.             false value and no <alternate> is specified, then the result
  406.             of the expression is unspecified.
  407.  
  408.         (ACCESS <variable> <env>)
  409.  
  410.             <Env> is evaluated producing an environment.  The result is
  411.             the value of <variable> in this environment.
  412.  
  413.         (SET! <variable> <expression>)
  414.  
  415.             <Expression> is evaluated, and the resulting value is stored
  416.             in the location to which <variable> is bound.  <Variable>
  417.             must be bound in some region or at the top level. The result
  418.             of the set! expression is unspecified.
  419.  
  420.         (SET! (ACCESS <variable> <env>) <value>)
  421.  
  422.             <Env> is evaluated producing an environment.  <Value> is
  423.             evaluated and the resulting value is stored as the value of
  424.             <variable> in this environment.  The result of the set!
  425.             expression is unspecified.
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.         XSCHEME                   EXPRESSIONS                     Page 8
  463.  
  464.  
  465.         (COND <clause>...)
  466.  
  467.             Each clause should be of the form
  468.  
  469.                 (<test> <expression>...)
  470.  
  471.             where <test> is any expression.  The last <clause> may be an
  472.             "else clause," which has the form
  473.  
  474.                 (ELSE <expression>...)
  475.  
  476.             A cond expression is evaluated by evaluating the <test>
  477.             expressions of successive <clause>s in order until one of
  478.             them evaluates to a true value.  When a <test> evaluates to
  479.             a true value, then the remaining <expression>s in its
  480.             <clause> are evaluated in order, and the result of the last
  481.             <expression> in the <clause> is returned as the result of
  482.             the entire cond expression.  If the selected <clause>
  483.             contains only the <test> and no <expression>s, then the
  484.             value of the <test> is returned as the result.  If all
  485.             <test>s evaluate to false values, and there is no else
  486.             clause, then the result of the conditional expression is
  487.             unspecified; if there is an else clause, then its
  488.             <expression>s are evaluated, and the value of the last one
  489.             is returned.
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.         XSCHEME                   EXPRESSIONS                     Page 9
  529.  
  530.  
  531.         (AND <test>...)
  532.  
  533.             The <test> expressions are evaluated from left to right, and
  534.             the value of the first expression that evaluates to a false
  535.             value is returned.  Any remaining expressions are not
  536.             evaluated.  If all the expressions evaluate to true values,
  537.             the value of the last expression is returned.  If there are
  538.             no expressions then #t is returned.
  539.  
  540.         (OR <test>...)
  541.  
  542.             The <test> expressions are evaluated from left to right, and
  543.             the value of the first expression that evaluates to a true
  544.             value is returned.  Any remaining expressions are not
  545.             evaluated.  If all expressions evaluate to false values, the
  546.             value of the last expression is returned.  If there are no
  547.             expressions then #f is returned.
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.         XSCHEME                  BINDING FORMS                   Page 10
  595.  
  596.  
  597.         BINDING FORMS
  598.  
  599.         (LET [<name>] <bindings> <body>)
  600.  
  601.             <Bindings> should have the form
  602.  
  603.                 ((<variable> <init>)...)
  604.  
  605.             where each <init> is an expression, and <body> should be a
  606.             sequence of one or more expressions.  The <init>s are
  607.             evaluated in the current envirnoment, the <variable>s are
  608.             bound to fresh locations holding the results, the <body> is
  609.             evaluated in the extended environment, and the value of the
  610.             last expression of <body> is returned.  Each binding of a
  611.             <variable> has <body> as its region.
  612.  
  613.             If a name is supplied, a procedure that takes the bound
  614.             variables as its arguments and has the body of the LET as
  615.             its body is bound to that name.
  616.  
  617.         (LET* <bindings> <body>)
  618.  
  619.             Same as LET except that the bindings are done sequentially
  620.             from left to right and the bindings to the left are visible
  621.             while evaluating the initialization expressions for each
  622.             variable.
  623.  
  624.         (LETREC <bindings> <body>)
  625.  
  626.             <Bindings> should have the form
  627.  
  628.                 ((<variable> <init>)...)
  629.  
  630.             and <body> should be a sequence of one or more expressions.
  631.             The <variable>s are bound to fresh locations holding
  632.             undefined values; the <init>s are evaluated in the resulting
  633.             environment; each <variable>  is assigned to the result of
  634.             the corresponding <init>; the <body> is evaluated in the
  635.             resulting environment; and the value of the last expression
  636.             in <body> is returned.  Each binding of a <variable> has the
  637.             entire letrec expression as its region, making it possible
  638.             to define mutually recursive procedures.  One restriction of
  639.             letrec is very important:  it must be possible to evaluate
  640.             each <init> without referring to the value of any
  641.             <variable>.  If this restriction is violated, then the
  642.             effect is undefined, and an error may be signalled during
  643.             evaluation of the <init>s.  The restriction is necessary
  644.             because Scheme passes arguments by value rather than by
  645.             name.  In the most common uses of letrec, all the <init>s
  646.             are lambda expressions and the restriction is satisfied
  647.             automatically.
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.         XSCHEME                    SEQUENCING                    Page 11
  661.  
  662.  
  663.             SEQUENCING
  664.  
  665.             (BEGIN <expression>...)
  666.             (SEQUENCE <expression>...)
  667.  
  668.                 The <expression>s are evaluated sequentially from left
  669.                 to right, and the value of the last <expression> is
  670.                 returned.  This expression type is used to sequence side
  671.                 effects such as input and output.
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.         XSCHEME                DELAYED EVALUATION                Page 12
  727.  
  728.  
  729.             DELAYED EVALUATION
  730.  
  731.             (CONS-STREAM expr1 expr2)
  732.  
  733.                 Create a cons stream whose head is expr1 (which is
  734.                 evaluated immediately) and whose tail is expr2 (whose
  735.                 evaluation is delayed until TAIL is called).  To use
  736.                 CONS-STREAM, enter the following access procedures:
  737.  
  738.                     (define head car)
  739.                     (define (tail stream) (force (cdr stream)))
  740.  
  741.             (DELAY <expression>)
  742.  
  743.                 Evaluating this expression creates a "promise" to
  744.                 evaluate <expression>  at a later time.
  745.  
  746.             (FORCE promise)
  747.  
  748.                 Applying FORCE to a promise generated by DELAY requests
  749.                 that the promise produce the value of the expression
  750.                 passed to DELAY.  The first time a promise is FORCEed,
  751.                 the DELAY expression is evaluated and the value stored.
  752.                 On subsequent calls to FORCE with the same promise, the
  753.                 saved value is returned.
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.         XSCHEME                    ITERATION                     Page 13
  793.  
  794.  
  795.             ITERATION
  796.  
  797.             (WHILE <test> <expression>...)
  798.  
  799.                 While is an iteration construct.  Each iteration begins
  800.                 by evaluating <test>; if the result is false, then the
  801.                 loop terminates and the value of <test> is returned as
  802.                 the value of the while expression.  If <test>  evaluates
  803.                 to a true value, then the <expression>s are evaluated in
  804.                 order for effect and the next iteration begins.
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.         XSCHEME                   DEFINITIONS                    Page 14
  859.  
  860.  
  861.             DEFINITIONS
  862.  
  863.             (DEFINE <variable> <expression>)
  864.  
  865.                 Define a variable and give it an initial value.
  866.  
  867.             (DEFINE (<variable> <formals>) <body>)
  868.  
  869.                 Define a procedure.
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.         XSCHEME                  LIST FUNCTIONS                  Page 15
  925.  
  926.  
  927.             LIST FUNCTIONS
  928.  
  929.             (CONS expr1 expr2)
  930.  
  931.                 Create a new pair whose car is expr1 and whose cdr is
  932.                 expr2.
  933.  
  934.             (CAR pair)
  935.  
  936.                 Extract the car of a pair.
  937.  
  938.             (CDR pair)
  939.  
  940.                 Extract the cdr of a pair.
  941.  
  942.             (CxxR pair)
  943.             (CxxxR pair)
  944.             (CxxxxR pair)
  945.  
  946.                 These functions are short for combinations of CAR and
  947.                 CDR.  Each 'x' is stands for either 'A' or 'D'.  An 'A'
  948.                 stands for the CAR function and a 'D' stands for the CDR
  949.                 function.  For instance, (CADR x) is the same as (CAR
  950.                 (CDR x)).
  951.  
  952.             (LIST expr...)
  953.  
  954.                 Create a list whose elements are the arguments to the
  955.                 function.  This function can take an arbitrary number of
  956.                 arguments.  Passing no arguments results in the empty
  957.                 list.
  958.  
  959.             (APPEND list...)
  960.  
  961.                 Append lists to form a single list.  This function takes
  962.                 an arbitrary number of arguments.  Passing no arguments
  963.                 results in the empty list.
  964.  
  965.             (REVERSE list)
  966.  
  967.                 Create a list whose elements are the same as the
  968.                 argument except in reverse order.
  969.  
  970.             (LAST-PAIR list)
  971.  
  972.                 Return the last pair in a list.
  973.  
  974.             (LENGTH list)
  975.  
  976.                 Compute the length of a list.
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.         XSCHEME                  LIST FUNCTIONS                  Page 16
  991.  
  992.  
  993.             (MEMBER expr list)
  994.             (MEMV expr list)
  995.             (MEMQ expr list)
  996.  
  997.                 Find an element in a list.  Each of these functions
  998.                 searches the list looking for an element that matches
  999.                 expr.  If a matching element is found, the remainder of
  1000.                 the list starting with that element is returned.  If no
  1001.                 matching element is found, the empty list is returned.
  1002.                 The functions differ in the test used to determine if an
  1003.                 element matches expr.  The MEMBER function uses EQUAL?,
  1004.                 the MEMV function uses EQV?  and the MEMQ function uses
  1005.                 EQ?.
  1006.  
  1007.             (ASSOC expr alist)
  1008.             (ASSV expr alist)
  1009.             (ASSQ expr alist)
  1010.  
  1011.                 Find an entry in an association list.  An association
  1012.                 list is a list of pairs.  The car of each pair is the
  1013.                 key and the cdr is the value.  These functions search an
  1014.                 association list for a pair whose key matches expr.  If
  1015.                 a matching pair is found, it is returned.  Otherwise,
  1016.                 the empty list is returned.  The functions differ in the
  1017.                 test used to determine if a key matches expr.  The ASSOC
  1018.                 function uses EQUAL?, the ASSV function uses EQV?  and
  1019.                 the ASSQ function uses EQ?.
  1020.  
  1021.             (LIST-REF list n)
  1022.  
  1023.                 Return the nth element of a list (zero based).
  1024.  
  1025.             (LIST-TAIL list n)
  1026.  
  1027.                 Return the sublist obtained by removing the first n
  1028.                 elements of list.
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.         XSCHEME            DESTRUCTIVE LIST FUNCTIONS            Page 17
  1057.  
  1058.  
  1059.             DESTRUCTIVE LIST FUNCTIONS
  1060.  
  1061.             (SET-CAR! pair expr)
  1062.  
  1063.                 Set the car of a pair to expr.  The value returned by
  1064.                 this procedure is unspecified.
  1065.  
  1066.             (SET-CDR! pair expr)
  1067.  
  1068.                 Set the cdr of a pair to expr.  The value returned by
  1069.                 this procedure is unspecified.
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.         XSCHEME                 SYMBOL FUNCTIONS                 Page 18
  1123.  
  1124.  
  1125.             SYMBOL FUNCTIONS
  1126.  
  1127.             (BOUND? sym)
  1128.  
  1129.                 Returns #t if a global value is bound to the symbol and
  1130.                 #f otherwise.
  1131.  
  1132.             (SYMBOL-VALUE sym)
  1133.  
  1134.                 Get the global value of a symbol.
  1135.  
  1136.             (SET-SYMBOL-VALUE! sym expr)
  1137.  
  1138.                 Set the global value of a symbol.  The value returned by
  1139.                 this procedure is unspecified.
  1140.  
  1141.             (SYMBOL-PLIST sym)
  1142.  
  1143.                 Get the property list associated with a symbol.
  1144.  
  1145.             (SET-SYMBOL-PLIST! sym plist)
  1146.  
  1147.                 Set the property list associate with a symbol.  The
  1148.                 value returned by this procedure is unspecified.
  1149.  
  1150.             (GENSYM [sym|str|num])
  1151.  
  1152.                 Generate a new, uninterned symbol.  The print name of
  1153.                 the symbol will consist of a prefix with a number
  1154.                 appended.  The initial prefix is "G" and the initial
  1155.                 number is 1.  If a symbol is specified as an argument,
  1156.                 the prefix is set to the print name of that symbol.  If
  1157.                 a string is specified, the prefix is set to that string.
  1158.                 If a number is specified, the numeric suffix is set to
  1159.                 that number.  After the symbol is generated, the number
  1160.                 is incremented so subsequent calls to GENSYM will
  1161.                 generate numbers in sequence.
  1162.  
  1163.             (GET sym prop)
  1164.  
  1165.                 Get the value of a property of a symbol.  The prop
  1166.                 argument is a symbol that is the property name.  If a
  1167.                 property with that name exists on the symbols property
  1168.                 list, the value of the property is returned.  Otherwise,
  1169.                 the empty list is returned.
  1170.  
  1171.             (PUT sym prop expr)
  1172.  
  1173.                 Set the value of a property of a symbol.  The prop
  1174.                 argument is a symbol that is the property name.  The
  1175.                 property/value combination is added to the property list
  1176.                 of the symbol.
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.         XSCHEME                 VECTOR FUNCTIONS                 Page 19
  1189.  
  1190.  
  1191.             VECTOR FUNCTIONS
  1192.  
  1193.             (VECTOR expr...)
  1194.  
  1195.                 Create a vector whose elements are the arguments to the
  1196.                 function.  This function can take an arbitrary number of
  1197.                 arguments.  Passing no arguments results in a zero
  1198.                 length vector.
  1199.  
  1200.             (MAKE-VECTOR len)
  1201.  
  1202.                 Make a vector of the specified length.
  1203.  
  1204.             (VECTOR-LENGTH vect)
  1205.  
  1206.                 Get the length of a vector.
  1207.  
  1208.             (VECTOR-REF vect n)
  1209.  
  1210.                 Return the nth element of a vector (zero based).
  1211.  
  1212.             (VECTOR-SET! vect n expr)
  1213.  
  1214.                 Set the nth element of a vector (zero based).
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.         XSCHEME                 ARRAY FUNCTIONS                  Page 20
  1255.  
  1256.  
  1257.             ARRAY FUNCTIONS
  1258.  
  1259.             (MAKE-ARRAY d1 d2...)
  1260.  
  1261.                 Make an array (vector of vectors) with the specified
  1262.                 dimensions.  At least one dimension must be specified.
  1263.  
  1264.             (ARRAY-REF array s1 s2...)
  1265.  
  1266.                 Get an array element.  The sn arguments are integer
  1267.                 subscripts (zero based).
  1268.  
  1269.             (ARRAY-SET! array s1 s2... expr)
  1270.  
  1271.                 Set an array element.  The sn arguments are integer
  1272.                 subscripts (zero based).
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.         XSCHEME               CONVERSION FUNCTIONS               Page 21
  1321.  
  1322.  
  1323.             CONVERSION FUNCTIONS
  1324.  
  1325.             (SYMBOL->STRING sym)
  1326.  
  1327.                 Convert a symbol to a string.  Returns the print name of
  1328.                 the symbol as a string.
  1329.  
  1330.             (STRING->SYMBOL str)
  1331.  
  1332.                 Convert a string to a symbol.  Returns a symbol with the
  1333.                 string as its print name.  This can either be a new
  1334.                 symbol or an existing one with the same print name.
  1335.  
  1336.             (VECTOR->LIST vect)
  1337.  
  1338.                 Convert a vector to a list.  Returns a list of the
  1339.                 elements of the vector.
  1340.  
  1341.             (LIST->VECTOR list)
  1342.  
  1343.                 Convert a list to a vector.  Returns a vector of the
  1344.                 elements of the list.
  1345.  
  1346.             (STRING->LIST str)
  1347.  
  1348.                 Convert a string to a list.  Returns a list of the
  1349.                 characters in the string.
  1350.  
  1351.             (LIST->STRING list)
  1352.  
  1353.                 Convert a list of character to a string.  Returns a
  1354.                 string whose characters are the elements of the list.
  1355.  
  1356.             (CHAR->INTEGER char)
  1357.  
  1358.                 Convert a character to an integer.  Returns the ASCII
  1359.                 code of the character as an integer.
  1360.  
  1361.             (INTEGER->CHAR n)
  1362.  
  1363.                 Convert an integer ASCII code to a character.  Returns
  1364.                 the character whose ASCII code is the integer.
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.         XSCHEME                 TYPE PREDICATES                  Page 22
  1387.  
  1388.  
  1389.             TYPE PREDICATE FUNCTIONS
  1390.  
  1391.             (NOT expr)
  1392.  
  1393.                 Returns #t if the expression is #f and #t otherwise.
  1394.  
  1395.             (NULL? expr)
  1396.  
  1397.                 Returns #t if the expression is the empty list and #f
  1398.                 otherwise.
  1399.  
  1400.             (ATOM? expr)
  1401.  
  1402.                 Returns #f if the expression is a pair and #t otherwise.
  1403.  
  1404.             (LIST? expr)
  1405.  
  1406.                 Returns #t if the expression is either a pair or the
  1407.                 empty list and #f otherwise.
  1408.  
  1409.             (NUMBER? expr)
  1410.  
  1411.                 Returns #t if the expression is a number and #f
  1412.                 otherwise.
  1413.  
  1414.             (BOOLEAN? expr)
  1415.  
  1416.                 Returns #t if the expression is either #t or #f and #f
  1417.                 otherwise.
  1418.  
  1419.             (PAIR? expr)
  1420.  
  1421.                 Returns #t if the expression is a pair and #f otherwise.
  1422.  
  1423.             (SYMBOL? expr)
  1424.  
  1425.                 Returns #t if the expression is a symbol and #f
  1426.                 otherwise.
  1427.  
  1428.             (COMPLEX? expr)
  1429.  
  1430.                 Returns #t if the expression is a complex number and #f
  1431.                 otherwise.
  1432.                 Note:  Complex numbers are not yet supported by XScheme.
  1433.  
  1434.             (REAL? expr)
  1435.  
  1436.                 Returns #t if the expression is a real number and #f
  1437.                 otherwise.
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450.  
  1451.  
  1452.         XSCHEME                 TYPE PREDICATES                  Page 23
  1453.  
  1454.  
  1455.             (RATIONAL? expr)
  1456.  
  1457.                 Returns #t if the expression is a rational number and #f
  1458.                 otherwise.
  1459.                 Note:  Rational numbers are not yet supported by
  1460.                 XScheme.
  1461.  
  1462.             (INTEGER? expr)
  1463.  
  1464.                 Returns #t if the expression is an integer and #f
  1465.                 otherwise.
  1466.  
  1467.             (CHAR? expr)
  1468.  
  1469.                 Returns #t if the expression is a character and #f
  1470.                 otherwise.
  1471.  
  1472.             (STRING? expr)
  1473.  
  1474.                 Returns # if the expression is a string and #f
  1475.                 otherwise.
  1476.  
  1477.             (VECTOR? expr)
  1478.  
  1479.                 Returns #t if the expression is a vector and #f
  1480.                 otherwise.
  1481.  
  1482.             (PROCEDURE? expr)
  1483.  
  1484.                 Returns #t if the expression is a procedure (closure)
  1485.                 and #f otherwise.
  1486.  
  1487.             (PORT? expr)
  1488.  
  1489.                 Returns #t if the expression is a port and #f otherwise.
  1490.  
  1491.             (INPUT-PORT? expr)
  1492.  
  1493.                 Returns #t if the expression is an input port and #f
  1494.                 otherwise.
  1495.  
  1496.             (OUTPUT-PORT? expr)
  1497.  
  1498.                 Returns #t if the expression is an output port and #f
  1499.                 otherwise.
  1500.  
  1501.             (OBJECT? expr)
  1502.  
  1503.                 Returns #t if the expression is an object and #f
  1504.                 otherwise.
  1505.  
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.         XSCHEME                 TYPE PREDICATES                  Page 24
  1519.  
  1520.  
  1521.             (EOF-OBJECT? expr)
  1522.  
  1523.                 Returns #t if the expression is the object returned by
  1524.                 READ upon detecting an end of file condition and #f
  1525.                 otherwise.
  1526.  
  1527.             (DEFAULT-OBJECT? expr)
  1528.  
  1529.                 Returns #t if the expression is the object passed as the
  1530.                 default value of an optional parameter to a procedure
  1531.                 when that parameter is omitted from a call and #f
  1532.                 otherwise.
  1533.  
  1534.             (ENVIRONMENT? x)
  1535.  
  1536.                 Returns #t if the expression is an environment and #f
  1537.                 otherwise.
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.  
  1584.         XSCHEME               EQUALITY PREDICATES                Page 25
  1585.  
  1586.  
  1587.             EQUALITY PREDICATES
  1588.  
  1589.             (EQUAL? expr1 expr2)
  1590.  
  1591.                 Recursively compares two objects to determine if their
  1592.                 components are the same and returns #t if they are the
  1593.                 same and #f otherwise.
  1594.  
  1595.             (EQV? expr1 expr2)
  1596.  
  1597.                 Compares two objects to determine if they are the same
  1598.                 object.  Returns #t if they are the same and #f
  1599.                 otherwise.  This function does not compare the elements
  1600.                 of lists, vectors or strings but will compare all types
  1601.                 of numbers.
  1602.  
  1603.             (EQ? expr1 expr2)
  1604.  
  1605.                 Compares two objects to determine if they are the same
  1606.                 object.  Returns #t if they are the same and #f
  1607.                 otherwise.  This function performs a low level address
  1608.                 compare on two objects and may return #f for objects
  1609.                 that appear on the surface to be the same.  This is
  1610.                 because the objects are not stored uniquely in memory.
  1611.                 For instance, numbers may appear to be equal, but EQ?
  1612.                 will return #f when comparing them if they are stored at
  1613.                 different addresses.  The advantage of this function is
  1614.                 that it is faster than the others.  Symbols are
  1615.                 guaranteed to compare correctly, so EQ? can safely be
  1616.                 used to compare them.
  1617.  
  1618.  
  1619.  
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.  
  1631.  
  1632.  
  1633.  
  1634.  
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.  
  1646.  
  1647.  
  1648.  
  1649.  
  1650.         XSCHEME               ARITHMETIC FUNCTIONS               Page 26
  1651.  
  1652.  
  1653.             ARITHMETIC FUNCTIONS
  1654.  
  1655.             (ZERO? n)
  1656.  
  1657.                 Returns #t if the number is zero and #f otherwise.
  1658.  
  1659.             (POSITIVE? n)
  1660.  
  1661.                 Returns #t if the number is positive and #f otherwise.
  1662.  
  1663.             (NEGATIVE? n)
  1664.  
  1665.                 Returns #t if the number is negative and #f otherwise.
  1666.  
  1667.             (ODD? n)
  1668.  
  1669.                 Returns #t if the integer is odd and #f otherwise.
  1670.  
  1671.             (EVEN? n)
  1672.  
  1673.                 Returns #t if the integer is even and #f otherwise.
  1674.  
  1675.             (EXACT? n)
  1676.  
  1677.                 Returns #t if the number is exact and #f otherwise.
  1678.                 Note:  This function always returns #f in XScheme since
  1679.                 exact numbers are not yet supported.
  1680.  
  1681.             (INEXACT? n)
  1682.  
  1683.                 Returns #t if the number is inexact and #f otherwise.
  1684.                 Note:  This function always returns #t in XScheme since
  1685.                 exact numbers are not yet supported.
  1686.  
  1687.             (TRUNCATE n)
  1688.  
  1689.                 Truncates a number to an integer and returns the
  1690.                 resulting value.
  1691.  
  1692.             (FLOOR n)
  1693.  
  1694.                 Returns the largest integer not larger than n.
  1695.  
  1696.             (CEILING n)
  1697.  
  1698.                 Returns the smallest integer not smaller than n.
  1699.  
  1700.             (ROUND n)
  1701.  
  1702.                 Returns the closest integer to n, rounding to even when
  1703.                 n is halfway between two integers.
  1704.  
  1705.             (1+ n)
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.         XSCHEME               ARITHMETIC FUNCTIONS               Page 27
  1717.  
  1718.  
  1719.                 Returns the result of adding one to the number.
  1720.  
  1721.             (-1+ n)
  1722.  
  1723.                 Returns the result of subtracting one from the number.
  1724.  
  1725.             (ABS n)
  1726.  
  1727.                 Returns the absolute value of the number.
  1728.  
  1729.             (GCD n1 n2)
  1730.  
  1731.                 Returns the greatest common divisor of the two numbers.
  1732.  
  1733.             (RANDOM n)
  1734.  
  1735.                 Returns a random number between zero and n-1 (n must be
  1736.                 an integer).
  1737.  
  1738.             (+ n1 n2...)
  1739.  
  1740.                 Returns the sum of the numbers.
  1741.  
  1742.             (- n)
  1743.  
  1744.                 Negates the number and returns the resulting value.
  1745.  
  1746.             (- n1 n2...)
  1747.  
  1748.                 Subtracts each remaining number from n1 and returns the
  1749.                 resulting value.
  1750.  
  1751.             (* n1 n2...)
  1752.  
  1753.                 Multiples the numbers and returns the resulting value.
  1754.  
  1755.             (/ n)
  1756.  
  1757.                 Returns 1/n.
  1758.  
  1759.             (/ n1 n2...)
  1760.  
  1761.                 Divides n1 by each of the remaining numbers and returns
  1762.                 the resulting value.
  1763.  
  1764.             (QUOTIENT n1 n2...)
  1765.  
  1766.                 Divides the integer n1 by each of the remaining numbers
  1767.                 and returns the resulting integer quotient.  This
  1768.                 function does integer division.
  1769.  
  1770.             (REMAINDER n1 n2)
  1771.  
  1772.                 Divides the integer n1 by the integer n2 and returns the
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.         XSCHEME               ARITHMETIC FUNCTIONS               Page 28
  1783.  
  1784.  
  1785.                 remainder.
  1786.  
  1787.             (MIN n1 n2...)
  1788.  
  1789.                 Returns the number with the minimum value.
  1790.  
  1791.             (MAX n1 n2...)
  1792.  
  1793.                 Returns the number with the maximum value.
  1794.  
  1795.             (SIN n)
  1796.  
  1797.                 Returns the sine of the number.
  1798.  
  1799.             (COS n)
  1800.  
  1801.                 Returns the cosine of the number.
  1802.  
  1803.             (TAN n)
  1804.  
  1805.                 Returns the tangent of the number.
  1806.  
  1807.             (ASIN n)
  1808.  
  1809.                 Returns the arc-sine of the number.
  1810.  
  1811.             (ACOS n)
  1812.  
  1813.                 Returns the arc-cosine of the number.
  1814.  
  1815.             (ATAN x)
  1816.  
  1817.                 Returns the arc-tangent of x.
  1818.  
  1819.             (ATAN y x)
  1820.  
  1821.                 Returns the arc-tangent of y/x.
  1822.  
  1823.             (EXP n)
  1824.  
  1825.                 Returns e raised to the n.
  1826.  
  1827.             (SQRT n)
  1828.  
  1829.                 Returns the square root of n.
  1830.  
  1831.             (EXPT n1 n2)
  1832.  
  1833.                 Returns n1 raised to the n2 power.
  1834.  
  1835.             (LOG n)
  1836.  
  1837.                 Returns the natural logarithm of n.
  1838.  
  1839.  
  1840.  
  1841.  
  1842.  
  1843.  
  1844.  
  1845.  
  1846.  
  1847.  
  1848.         XSCHEME           NUMERIC COMPARISON FUNCTIONS           Page 29
  1849.  
  1850.  
  1851.             NUMERIC COMPARISON FUNCTIONS
  1852.  
  1853.             (< n1 n2...)
  1854.             (= n1 n2...)
  1855.             (> n1 n2...)
  1856.             <<= n1 n2...)
  1857.             (>= n1 n2...)
  1858.  
  1859.                 These functions compare numbers and return #t if the
  1860.                 numbers match the predicate and #f otherwise.  For
  1861.                 instance, (< x y z) will return #t if x is less than y
  1862.                 and y is less than z.
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.  
  1870.  
  1871.  
  1872.  
  1873.  
  1874.  
  1875.  
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.  
  1888.  
  1889.  
  1890.  
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896.  
  1897.  
  1898.  
  1899.  
  1900.  
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906.  
  1907.  
  1908.  
  1909.  
  1910.  
  1911.  
  1912.  
  1913.  
  1914.         XSCHEME            BITWISE LOGICAL FUNCTIONS             Page 30
  1915.  
  1916.  
  1917.             BITWISE LOGICAL FUNCTIONS
  1918.  
  1919.             (LOGAND n1 n2...)
  1920.  
  1921.                 Returns the bitwise AND of the integer arguments.
  1922.  
  1923.             (LOGIOR n1 n2...)
  1924.  
  1925.                 Returns the bitwise inclusive OR of the integer
  1926.                 arguments.
  1927.  
  1928.             (LOGXOR n1 n2...)
  1929.  
  1930.                 Returns the bitwise exclusive OR of the integer
  1931.                 arguments.
  1932.  
  1933.             (LOGNOT n)
  1934.  
  1935.                 Returns the bitwise complement of n.
  1936.  
  1937.  
  1938.  
  1939.  
  1940.  
  1941.  
  1942.  
  1943.  
  1944.  
  1945.  
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954.  
  1955.  
  1956.  
  1957.  
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.  
  1965.  
  1966.  
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.  
  1976.  
  1977.  
  1978.  
  1979.  
  1980.         XSCHEME                 STRING FUNCTIONS                 Page 31
  1981.  
  1982.  
  1983.             STRING FUNCTIONS
  1984.  
  1985.             (STRING-LENGTH str)
  1986.  
  1987.                 Returns the length of the string.
  1988.  
  1989.             (STRING-NULL? str)
  1990.  
  1991.                 Returns #t if the string has a length of zero and #f
  1992.                 otherwise.
  1993.  
  1994.             (STRING-APPEND str1...)
  1995.  
  1996.                 Returns the result of appending the string arguments.
  1997.                 If no arguments are supplied, it returns the null
  1998.                 string.
  1999.  
  2000.             (STRING-REF str n)
  2001.  
  2002.                 Returns the nth character in a string.
  2003.  
  2004.             (SUBSTRING str start end)
  2005.  
  2006.                 Returns the substring of str starting at start and
  2007.                 ending at end (integers).  The range is inclusive of
  2008.                 start and exclusive of end.
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014.  
  2015.  
  2016.  
  2017.  
  2018.  
  2019.  
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.  
  2028.  
  2029.  
  2030.  
  2031.  
  2032.  
  2033.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.  
  2042.  
  2043.  
  2044.  
  2045.  
  2046.         XSCHEME           STRING COMPARISON FUNCTIONS            Page 32
  2047.  
  2048.  
  2049.             STRING COMPARISON FUNCTIONS
  2050.  
  2051.             (STRING<? str1 str2)
  2052.             (STRING=? str1 str2)
  2053.             (STRING>? str1 str2)
  2054.             (STRING<=? str1 str2)
  2055.             (STRING>=? str1 str2)
  2056.  
  2057.                 These functions compare strings and return #t if the
  2058.                 strings match the predicate and #f otherwise.  For
  2059.                 instance, (STRING< x y) will return #t if x is less than
  2060.                 y.  Case is significant.  #A does not match #a.
  2061.  
  2062.             (STRING-CI<? str1 str2)
  2063.             (STRING-CI=? str1 str2)
  2064.             (STRING-CI>? str1 str2)
  2065.             (STRING-CI<=? str1 str2)
  2066.             (STRING-CI>=? str1 str2)
  2067.  
  2068.                 These functions compare strings and return #t if the
  2069.                 strings match the predicate and #f otherwise.  For
  2070.                 instance, (STRING-CI< x y) will return #t if x is less
  2071.                 than y.  Case is not significant.  #A matches #a.
  2072.  
  2073.  
  2074.  
  2075.  
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.  
  2099.  
  2100.  
  2101.  
  2102.  
  2103.  
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111.  
  2112.         XSCHEME          CHARACTER COMPARISON FUNCTIONS          Page 33
  2113.  
  2114.  
  2115.             CHARACTER COMPARISON FUNCTIONS
  2116.  
  2117.             (CHAR<? ch1 ch2)
  2118.             (CHAR=? ch1 ch2)
  2119.             (CHAR>? ch1 ch2)
  2120.             (CHAR<=? ch1 ch2)
  2121.             (CHAR>=? ch1 ch2)
  2122.  
  2123.                 These functions compare characters and return #t if the
  2124.                 characters match the predicate and #f otherwise.  For
  2125.                 instance, (CHAR< x y) will return #t if x is less than
  2126.                 y.  Case is significant.  #A does not match #a.
  2127.  
  2128.             (CHAR-CI<? ch1 ch2)
  2129.             (CHAR-CI=? ch1 ch2)
  2130.             (CHAR-CI>? ch1 ch2)
  2131.             (CHAR-CI<=? ch1 ch2)
  2132.             (CHAR-CI>=? ch1 ch2)
  2133.  
  2134.                 These functions compare characters and return #t if the
  2135.                 characters match the predicate and #f otherwise.  For
  2136.                 instance, (CHAR-CI< x y) will return #t if x is less
  2137.                 than y.  Case is not significant.  #A matchs #a.
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.  
  2162.  
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.  
  2171.  
  2172.  
  2173.  
  2174.  
  2175.  
  2176.  
  2177.  
  2178.         XSCHEME              INPUT/OUTPUT FUNCTIONS              Page 34
  2179.  
  2180.  
  2181.             INPUT/OUTPUT FUNCTIONS
  2182.  
  2183.             (READ [port])
  2184.  
  2185.                 Reads an expression from the specified port.  If no port
  2186.                 is specified, the current input port is used.  Returns
  2187.                 the expression read or an object that satisfies the
  2188.                 default-object? predicate if it reaches the end of file
  2189.                 on the port.
  2190.  
  2191.             (READ-CHAR [port])
  2192.  
  2193.                 Reads a character from the specified port.  If no port
  2194.                 is specified, the current input port is used.  Returns
  2195.                 the character read or an object that satisfies the
  2196.                 default-object? predicate if it reaches the end of file
  2197.                 on the port.
  2198.  
  2199.             (READ-BYTE [port])
  2200.  
  2201.                 Reads a byte from the specified port.  If no port is
  2202.                 specified, the current input port is used.  Returns the
  2203.                 byte read or an object that satisfies the default-
  2204.                 object? predicate if it reaches the end of file on the
  2205.                 port.
  2206.  
  2207.             (WRITE expr [port])
  2208.             (PRIN1 expr [port])
  2209.  
  2210.                 Writes an expression to the specified port.  If no port
  2211.                 is specified, the current output port is used.  The
  2212.                 expression is written such that the READ function can
  2213.                 read it back.  This means that strings will be enclosed
  2214.                 in quotes and characters will be printed with #
  2215.                 notation.
  2216.  
  2217.             (WRITE-CHAR ch [port])
  2218.  
  2219.                 Writes a character to the specified port.  If no port is
  2220.                 specified, the current output port is used.
  2221.  
  2222.             (WRITE-BYTE ch [port])
  2223.  
  2224.                 Writes a byte to the specified port.  If no port is
  2225.                 specified, the current output port is used.
  2226.  
  2227.             (DISPLAY expr [port])
  2228.             (PRINC expr [port])
  2229.  
  2230.                 Writes an expression to the specified port.  If no port
  2231.                 is specified, the current output port is used.  The
  2232.                 expression is written without any quoting characters.
  2233.                 No quotes will appear around strings and characters are
  2234.                 written without the # notation.
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240.  
  2241.  
  2242.  
  2243.  
  2244.         XSCHEME              INPUT/OUTPUT FUNCTIONS              Page 35
  2245.  
  2246.  
  2247.             (NEWLINE [port])
  2248.  
  2249.                 Starts a new line on the specified port.  If no port is
  2250.                 specified, the current output port is used.
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.  
  2278.  
  2279.  
  2280.  
  2281.  
  2282.  
  2283.  
  2284.  
  2285.  
  2286.  
  2287.  
  2288.  
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295.  
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.  
  2305.  
  2306.  
  2307.  
  2308.  
  2309.  
  2310.         XSCHEME             OUTPUT CONTROL FUNCTIONS             Page 36
  2311.  
  2312.  
  2313.             OUTPUT CONTROL FUNCTIONS
  2314.  
  2315.             (PRINT-BREADTH [n])
  2316.  
  2317.                 Controls the maximum number of elements of a list that
  2318.                 will be printed.  If n is an integer, the maximum number
  2319.                 is set to n.  If it is #f, the limit is set to infinity.
  2320.                 This is the default.  If n is omitted from the call, the
  2321.                 current value is returned.
  2322.  
  2323.             (PRINT-DEPTH [n])
  2324.  
  2325.                 Controls the maximum number of levels of a nested list
  2326.                 that will be printed.  If n is an integer, the maximum
  2327.                 number is set to n.  If it is #f, the limit is set to
  2328.                 infinity.  This is the default.  If n is omitted from
  2329.                 the call, the current value is returned.
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.  
  2338.  
  2339.  
  2340.  
  2341.  
  2342.  
  2343.  
  2344.  
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350.  
  2351.  
  2352.  
  2353.  
  2354.  
  2355.  
  2356.  
  2357.  
  2358.  
  2359.  
  2360.  
  2361.  
  2362.  
  2363.  
  2364.  
  2365.  
  2366.  
  2367.  
  2368.  
  2369.  
  2370.  
  2371.  
  2372.  
  2373.  
  2374.  
  2375.  
  2376.         XSCHEME                FILE I/O FUNCTIONS                Page 37
  2377.  
  2378.  
  2379.             FILE I/O FUNCTIONS
  2380.  
  2381.             All four of the following OPEN functions take an optional
  2382.             argument to indicate that file I/O is to be done in binary
  2383.             mode.  For binary files, this argument should be the symbol
  2384.             BINARY.  For text files, the argument can be left out or the
  2385.             symbol TEXT can be supplied.
  2386.  
  2387.             (OPEN-INPUT-FILE str ['binary])
  2388.  
  2389.                 Opens the file named by the string and returns an input
  2390.                 port.
  2391.  
  2392.             (OPEN-OUTPUT-FILE str ['binary])
  2393.  
  2394.                 Creates the file named by the string and returns an
  2395.                 output port.
  2396.  
  2397.             (OPEN-APPEND-FILE str ['binary])
  2398.  
  2399.                 Opens the file named by the string for appending returns
  2400.                 an output port.
  2401.  
  2402.             (OPEN-UPDATE-FILE str ['binary])
  2403.  
  2404.                 Opens the file named by the string for input and output
  2405.                 and returns an input/output port.
  2406.  
  2407.             (GET-FILE-POSITION port)
  2408.  
  2409.                 Returns the current file position as an offset in bytes
  2410.                 from the beginning of the file.
  2411.  
  2412.             (SET-FILE-POSITION! port offset whence)
  2413.  
  2414.                 Sets the current file position as an offset in bytes
  2415.                 from the beginning of the file (when whence equals 0),
  2416.                 the current file position (when whence equals 1) or the
  2417.                 end of the file (when whence equals 2).  Returns the new
  2418.                 file position as an offset from the start of the file.
  2419.  
  2420.             (CLOSE-PORT port)
  2421.  
  2422.                 Closes any port.
  2423.  
  2424.             (CLOSE-INPUT-PORT port)
  2425.  
  2426.                 Closes an input port.
  2427.  
  2428.             (CLOSE-OUTPUT-PORT port)
  2429.  
  2430.                 Closes an output port.
  2431.  
  2432.  
  2433.  
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.  
  2442.         XSCHEME                FILE I/O FUNCTIONS                Page 38
  2443.  
  2444.  
  2445.             (CALL-WITH-INPUT-FILE str proc)
  2446.  
  2447.                 Open the file whose name is specifed by str and call
  2448.                 proc passing the resulting input port as an argument.
  2449.                 When proc returns, close the file and return the value
  2450.                 returned by proc as the result.
  2451.  
  2452.             (CALL-WITH-OUTPUT-FILE str proc)
  2453.  
  2454.                 Create the file whose name is specifed by str and call
  2455.                 proc passing the resulting output port as an argument.
  2456.                 When proc returns, close the file and return the value
  2457.                 returned by proc as the result.
  2458.  
  2459.             (CURRENT-INPUT-PORT)
  2460.  
  2461.                 Returns the current input port.
  2462.  
  2463.             (CURRENT-OUTPUT-PORT)
  2464.  
  2465.                 Returns the current output port.
  2466.  
  2467.  
  2468.  
  2469.  
  2470.  
  2471.  
  2472.  
  2473.  
  2474.  
  2475.  
  2476.  
  2477.  
  2478.  
  2479.  
  2480.  
  2481.  
  2482.  
  2483.  
  2484.  
  2485.  
  2486.  
  2487.  
  2488.  
  2489.  
  2490.  
  2491.  
  2492.  
  2493.  
  2494.  
  2495.  
  2496.  
  2497.  
  2498.  
  2499.  
  2500.  
  2501.  
  2502.  
  2503.  
  2504.  
  2505.  
  2506.  
  2507.  
  2508.         XSCHEME                 CONTROL FEATURES                 Page 39
  2509.  
  2510.  
  2511.             CONTROL FEATURES
  2512.  
  2513.             (EVAL expr)
  2514.  
  2515.                 Evaluate the expression in the global environment and
  2516.                 return its value.
  2517.  
  2518.             (APPLY proc args)
  2519.  
  2520.                 Apply the procedure to the list of arguments and return
  2521.                 the result.
  2522.  
  2523.             (MAP proc list...)
  2524.  
  2525.                 Apply the procedure to argument lists formed by taking
  2526.                 corresponding elements from each list.  Form a list from
  2527.                 the resulting values and return that list as the result
  2528.                 of the MAP call.
  2529.  
  2530.             (FOR-EACH fun list...)
  2531.  
  2532.                 Apply the procedure to argument lists formed by taking
  2533.                 corresponding elements from each list.  The values
  2534.                 returned by the procedure applications are discarded.
  2535.                 The value returned by FOR-EACH is unspecified.
  2536.  
  2537.             (CALL-WITH-CURRENT-CONTINUATION proc)
  2538.             (CALL/CC proc)
  2539.  
  2540.                 Form an "escape procedure" from the current continuation
  2541.                 and pass it as an argument to proc.  Calling the escape
  2542.                 procedure with a single argument will cause that
  2543.                 argument to be passed to the continuation that was in
  2544.                 effect when the CALL-WITH-CURRENT-CONTINUATION procedure
  2545.                 was called.
  2546.  
  2547.  
  2548.  
  2549.  
  2550.  
  2551.  
  2552.  
  2553.  
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.  
  2570.  
  2571.  
  2572.  
  2573.  
  2574.         XSCHEME              ENVIRONMENT FUNCTIONS               Page 40
  2575.  
  2576.  
  2577.             ENVIRONMENT FUNCTIONS
  2578.  
  2579.             (THE-ENVIRONMENT)
  2580.  
  2581.                 Returns the current environment.
  2582.  
  2583.             (PROCEDURE-ENVIRONMENT proc)
  2584.  
  2585.                 Returns the environment from a procedure closure.
  2586.  
  2587.             (ENVIRONMENT-BINDINGS env)
  2588.  
  2589.                 Returns an association list corresponding to the top
  2590.                 most frame of the specified environment.
  2591.  
  2592.             (ENVIRONMENT-PARENT env)
  2593.  
  2594.                 Returns the parent environment of the specified
  2595.                 environment.
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607.  
  2608.  
  2609.  
  2610.  
  2611.  
  2612.  
  2613.  
  2614.  
  2615.  
  2616.  
  2617.  
  2618.  
  2619.  
  2620.  
  2621.  
  2622.  
  2623.  
  2624.  
  2625.  
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639.  
  2640.         XSCHEME                UTILITY FUNCTIONS                 Page 41
  2641.  
  2642.  
  2643.             UTILITY FUNCTIONS
  2644.  
  2645.             (LOAD str)
  2646.  
  2647.                 Read and evaluate each expression from the specified
  2648.                 file.
  2649.  
  2650.             (LOAD-NOISILY str)
  2651.  
  2652.                 Read and evaluate each expression from the specified
  2653.                 file and print the results to the current output port.
  2654.  
  2655.             (TRANSCRIPT-ON str)
  2656.  
  2657.                 Opens a transcript file with the specified name and
  2658.                 begins logging the interactive session to that file.
  2659.  
  2660.             (TRANSCRIPT-OFF)
  2661.  
  2662.                 Closes the current transcript file.
  2663.  
  2664.             (EXIT)
  2665.  
  2666.                 Exits from XScheme back to the operating system.
  2667.  
  2668.             (GC [ni vi])
  2669.  
  2670.                 Invokes the garbage collector and returns information on
  2671.                 memory usage.  If ni and vi are specified, they must be
  2672.                 integers.  Node and vector space are expanded by those
  2673.                 amounts respectively and no garbage collection is
  2674.                 triggered.  GC returns an array of six values: the
  2675.                 number of calls to the garbage collector, the total
  2676.                 number of nodes, the current number of free nodes, the
  2677.                 number of node segments, the number of vector segments
  2678.                 and the total number of bytes allocated to the heap.
  2679.  
  2680.             (RESET)
  2681.  
  2682.                 Returns to the top level read/eval/print loop.
  2683.  
  2684.  
  2685.  
  2686.  
  2687.  
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693.  
  2694.  
  2695.  
  2696.  
  2697.  
  2698.  
  2699.  
  2700.  
  2701.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.         XSCHEME                 SYSTEM FUNCTIONS                 Page 42
  2707.  
  2708.  
  2709.             SYSTEM FUNCTIONS
  2710.  
  2711.             (%CAR pair)
  2712.             (%CDR pair)
  2713.             (%SET-CAR! pair expr)
  2714.             (%SET-CDR! pair expr)
  2715.             (%VECTOR-LENGTH vect)
  2716.             (%VECTOR-REF vect n)
  2717.             (%VECTOR-SET! vect n expr)
  2718.  
  2719.                 These functions do the same as their counterparts
  2720.                 without the leading '%' character.  The difference is
  2721.                 that they don't check the type of their first argument.
  2722.                 This makes it possible to examine data structures that
  2723.                 have the same internal representation as pairs and
  2724.                 vectors.  It is *very* dangerous to modify objects using
  2725.                 these functions and there is no guarantee that future
  2726.                 releases of XScheme will represent objects in the same
  2727.                 way that the current version does.
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.  
  2752.  
  2753.  
  2754.  
  2755.  
  2756.  
  2757.  
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763.  
  2764.  
  2765.  
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.         XSCHEME              OBJECT REPRESENTATIONS              Page 43
  2773.  
  2774.  
  2775.                 OBJECT REPRESENTATIONS
  2776.  
  2777.                 This version of XScheme uses the following object
  2778.                 representations:
  2779.  
  2780.                     Closures are represented as pairs.  The car of the
  2781.                     pair is the compiled function and the cdr of the
  2782.                     pair is the saved environment.
  2783.  
  2784.                     Compiled functions are represented as vectors.  The
  2785.                     element at offset 0 is the bytecode string.  The
  2786.                     element at offset 1 is the function name.  The
  2787.                     element at offset 2 is a list of names of the
  2788.                     function arguments.  The elements at offsets above 2
  2789.                     are the literals refered to by the compiled
  2790.                     bytecodes.
  2791.  
  2792.                     Environments are represented as lists of vectors.
  2793.                     Each vector is an environment frame.  The element at
  2794.                     offset 0 is a list of the symbols that are bound in
  2795.                     that frame.  The symbol values start at offset 1.
  2796.  
  2797.                     Objects are represented as vectors.  The element at
  2798.                     offset 0 is the class of the object.  The remaining
  2799.                     elements are the object's instance variable values.
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835. onments are represented as lists of vectors.
  2836.                     Each vector is an environment frame.  The element at
  2837.       scm/
  2838. 6
  2839.  
  2840.  
  2841.   31 
  2842.  
  2843.  
  2844.  
  2845. (define (%expand-macros expr)
  2846.   (if (pair? expr)
  2847.     (if (symbol? (car expr))
  2848.       (let ((expander (get (car expr) '%syntax)))
  2849.         (if expander
  2850.           (expander expr)
  2851.           (let ((expander (get (car expr) '%macro)))
  2852.             (if expander
  2853.               (%expand-macros (expander expr))
  2854.               (cons (car expr) (%expand-list (cdr expr)))))))
  2855.       (%expand-list expr))
  2856.     expr))
  2857.  
  2858. (define (%expand-list lyst)
  2859.   (if (pair? lyst)
  2860.     (cons (%expand-macros (car lyst)) (%expand-list (cdr lyst)))
  2861.     lyst))
  2862.  
  2863. (define (compile expr #!optional env)
  2864.   (if (default-object? env)
  2865.     (%compile (%expand-macros expr))
  2866.     (%compile (%expand-macros expr) env)))
  2867.  
  2868. (put 'macro '%macro
  2869.   (lambda (form)
  2870.     (list 'put
  2871.           (list 'quote (cadr form))
  2872.           (list 'quote '%macro)
  2873.           (caddr form))))
  2874.  
  2875. (macro syntax
  2876.   (lambda (form)
  2877.     #f))
  2878.  
  2879. (macro compiler-syntax
  2880.   (lambda (form)
  2881.     (list 'put
  2882.           (list 'quote (cadr form))
  2883.           (list 'quote '%syntax)
  2884.           (caddr form))))
  2885.  
  2886. (compiler-syntax quote
  2887.   (lambda (form) form))
  2888.           
  2889. (compiler-syntax lambda
  2890.   (lambda (form)
  2891.     (cons
  2892.       'lambda
  2893.       (cons
  2894.         (cadr form)
  2895.         (%expand-list (cddr form))))))
  2896.  
  2897. (compiler-syntax define
  2898.   (lambda (form)
  2899.     (cons
  2900.       'define
  2901.       (cons
  2902.         (cadr form)
  2903.         (%expand-list (cddr form))))))
  2904.   
  2905. (compiler-syntax set!
  2906.   (lambda (form)
  2907.     (cons
  2908.       'set!
  2909.       (cons
  2910.         (cadr form)
  2911.         (%expand-list (cddr form))))))
  2912.  
  2913. (define (%cond-expander lyst)
  2914.   (cond
  2915.       ((pair? lyst)
  2916.        (cons
  2917.          (if (pair? (car lyst))
  2918.            (%expand-list (car lyst))
  2919.            (car lyst))
  2920.          (%cond-expander (cdr lyst))))
  2921.       (else lyst)))
  2922.  
  2923. (compiler-syntax cond
  2924.   (lambda (form)
  2925.     (cons 'cond (%cond-expander (cdr form)))))
  2926.  
  2927. ; The following code for expanding let/let*/letrec was donated by:
  2928. ;
  2929. ; Harald Hanche-Olsen
  2930. ; The University of Trondheim
  2931. ; The Norwegian Institute of Technology
  2932. ; Division of Mathematics
  2933. ; N-7034 Trondheim NTH
  2934. ; Norway
  2935.  
  2936. (define (%expand-let-assignment pair)
  2937.   (if (pair? pair)
  2938.     (cons
  2939.       (car pair)
  2940.       (%expand-macros (cdr pair)))
  2941.     pair))
  2942.  
  2943. (define (%expand-let-form form)
  2944.   (cons
  2945.     (car form)
  2946.     (cons
  2947.       (let ((lyst (cadr form)))
  2948.         (if (pair? lyst)
  2949.           (map %expand-let-assignment lyst)
  2950.           lyst))
  2951.       (%expand-list (cddr form)))))
  2952.  
  2953. (compiler-syntax let %expand-let-form)
  2954. (compiler-syntax let* %expand-let-form)
  2955. (compiler-syntax letrec %expand-let-form)
  2956.  
  2957. (macro define-integrable
  2958.   (lambda (form)
  2959.     (cons 'define (cdr form))))
  2960.  
  2961. (macro declare
  2962.   (lambda (form) #f))
  2963. (car pair)
  2964.       (%expand-macros (cdr pair)))
  2965.     pair))
  2966.  
  2967. (define (%expand-let-form form)
  2968.   (cons
  2969.     (car form)
  2970.     (cons
  2971.       (let ((lyst (cadr form)))
  2972.         (if (pair? lyst)
  2973.           (map %expand-let-assignment lyst)
  2974.           lyst))
  2975.       (%expand-list (cddr form)))))
  2976.  
  2977. (compiler-syntax let %expand-let-form)
  2978. (compiler-syntax let* %expand-let-form)
  2979. (compiler-syntax letrec %expand-let-form)
  2980.  
  2981. (macro define-integrable
  2982.   (lambda (form)
  2983.     (cons 'definescm/qquote.s
  2984. 03604   6363
  2985.  
  2986.  
  2987.  
  2988. ;; Expands QUASIQUOTE/UNQUOTE/UNQUOTE according to Rev^3 Report specs.
  2989. ;;
  2990. ;; This file can be included as is in XSCHEME.INI, or can be incorporated 
  2991. ;; into MACROS.S, with expander functions anywhere and macros after
  2992. ;; after definition of COMPILER-SYNTAX
  2993.  
  2994. ;;; EXPANDER-FUNCTIONS: compilable under the core XSCHEME, can be evaluated
  2995. ;;; independently of MACRO system
  2996.  
  2997. (define APPEND-ME-SYM (gensym)) ;; must be a gensym to avoid capture in
  2998.                                 ;; certain (pathological) situations
  2999.  
  3000. (define QQ-EXPANDER
  3001.   (lambda (l)
  3002.           (letrec
  3003.            (
  3004.             (qq-lev 0) ; always >= 0
  3005.             (QQ-CAR-CDR
  3006.              (lambda (exp)
  3007.                      (let ((qq-car (qq (car exp)))
  3008.                            (qq-cdr (qq (cdr exp))))
  3009.                           (if (and (pair? qq-car)
  3010.                                    (eq? (car qq-car) append-me-sym))
  3011.                               (list 'append (cdr qq-car) qq-cdr)
  3012.                               (list 'cons qq-car qq-cdr)))))
  3013.             (QQ
  3014.              (lambda (exp)
  3015.                      (cond ((symbol? exp)
  3016.                             (list 'quote exp))
  3017.                            ((vector? exp)
  3018.                             (list 'list->vector (qq (vector->list exp))))
  3019.                            ((atom? exp) ; nil, number or boolean
  3020.                             exp)
  3021.                            ((eq? (car exp) 'quasiquote)
  3022.                             (set! qq-lev (1+ qq-lev))
  3023.                             (let ((qq-val
  3024.                                    (if (= qq-lev 1) ; min val after inc
  3025.                                        ; --> outermost level
  3026.                                        (qq (cadr exp))
  3027.                                        (qq-car-cdr exp))))
  3028.                                  (set! qq-lev (-1+ qq-lev))
  3029.                                  qq-val))
  3030.                            ((or (eq? (car exp) 'unquote)
  3031.                                 (eq? (car exp) 'unquote-splicing))
  3032.                             (set! qq-lev (-1+ qq-lev))
  3033.                             (let ((qq-val
  3034.                                    (if (= qq-lev 0) ; min val 
  3035.                                        ; --> outermost level
  3036.                                        (if (eq? (car exp) 'unquote-splicing)
  3037.                                            (cons append-me-sym 
  3038.                                                  (%expand-macros (cadr exp)))
  3039.                                            (%expand-macros (cadr exp))) 
  3040.                                        (qq-car-cdr exp))))
  3041.                                  (set! qq-lev (1+ qq-lev))
  3042.                                  qq-val))
  3043.                            (else
  3044.                             (qq-car-cdr exp)))))
  3045.             )
  3046.            (let ((expansion (qq l)))
  3047.                 (if check-qq-expansion-flag
  3048.                     (check-qq-expansion expansion)) ; error on failure
  3049.                 expansion))))
  3050.  
  3051. (define CHECK-QQ-EXPANSION
  3052.   (lambda (exp)
  3053.           (cond ((vector? exp)
  3054.                  (check-qq-expansion (vector->list exp)))
  3055.                 ((atom? exp)
  3056.                  #f)
  3057.                 (else
  3058.                  (if (eq? (car exp) append-me-sym)
  3059.                      (error "UNQUOTE-SPLICING in unspliceable position"
  3060.                             (list 'unquote-splicing (cdr exp)))
  3061.                      (or (check-qq-expansion (car exp))
  3062.                          (check-qq-expansion (cdr exp))))))))
  3063.  
  3064. (define CHECK-QQ-EXPANSION-FLAG #t) ; do checking
  3065.  
  3066. (define UNQ-EXPANDER
  3067.   (lambda (l) (error "UNQUOTE outside QUASIQUOTE" l)))
  3068.  
  3069. (define UNQ-SPL-EXPANDER
  3070.   (lambda (l) (error "UNQUOTE SPLICING outside QUASIQUOTE" l)))
  3071.  
  3072. ;;; MACROS: must be evaluated with MACRO system in place
  3073.  
  3074. (compiler-syntax QUASIQUOTE qq-expander)
  3075. (compiler-syntax UNQUOTE unq-expander)
  3076. (compiler-syntax UNQUOTE-SPLICING unq-spl-expander)
  3077.  
  3078. ;;; END
  3079.  
  3080. dr exp)))
  3081.                      (or (check-qq-expansion (car exp))
  3082.                          (check-qq-expansion (cdr exp))))))))
  3083.  
  3084. (define CHECK-QQ-EXPANSION-FLAG #t) ; do checking
  3085.  
  3086. (define UNQ-EXPANDER
  3087.   (lambda (l) (error "UNQUOTE outside QUASIQUOTE" l)))
  3088.  
  3089. (define UNQ-SPL-EXPANDER
  3090.   (lambda (l) (error "UNQUOTE SPLICING outside QUASIQUOTE" l)))
  3091.  
  3092. ;;; MACROS: mustsrc/
  3093. 5605   4652
  3094.  
  3095.  
  3096.    212 
  3097.  
  3098.  
  3099.  
  3100. #include <osbind.h>
  3101. #include "xscheme.h"
  3102.  
  3103. #define STRMAX         100             /* maximum length of a string constant */
  3104. /* char buf[STRMAX+1] = { 0 }; */
  3105. static char buf[200];
  3106.  
  3107. #define LBSIZE 200
  3108.  
  3109. /* set MWC memory parameters */
  3110. long _stksize = 16384;  /* stack must be 16K */
  3111.  
  3112. /* external variables */
  3113. extern LVAL s_unbound,true;
  3114. extern int errno;
  3115. extern FILE *tfp;
  3116. extern char buf[];
  3117.  
  3118. /* line buffer variables */
  3119. static char lbuf[LBSIZE];
  3120. static int  lpos[LBSIZE];
  3121. static int lindex;
  3122. static int lcount;
  3123. static int lposition;
  3124.  
  3125. /* osinit - initialize */
  3126. osinit(banner)
  3127.   char *banner;
  3128. {
  3129.     printf("\033v%s\n",banner);
  3130.     lposition = 0;
  3131.     lindex = 0;
  3132.     lcount = 0;
  3133. }
  3134.  
  3135. /* osfinish - clean up before a return to the operating system */
  3136. osfinish()
  3137. {
  3138. }
  3139.  
  3140. /* oserror - print an error message */
  3141. oserror(msg)
  3142.   char *msg;
  3143. {
  3144.     printf("error: %s\n",msg);
  3145. }
  3146.  
  3147. /* osrand - return a random number between 0 and n-1 */
  3148. int osrand(n)
  3149.   int n;
  3150. {
  3151.     return (rand() % n);
  3152. }
  3153.  
  3154. /* osaopen - open an ascii file */
  3155. FILE *osaopen(name,mode)
  3156.   char *name,*mode;
  3157. {
  3158.     return (fopen(name,mode));
  3159. }
  3160.  
  3161. /* osbopen - open a binary file */
  3162. FILE *osbopen(name,mode)
  3163.   char *name,*mode;
  3164. {
  3165.     char rmode[5];
  3166.     strcpy(rmode,mode); strcat(rmode,"b");
  3167.     return (fopen(name,rmode));
  3168. }
  3169.  
  3170. /* osclose - close a file */
  3171. int osclose(fp)
  3172.   FILE *fp;
  3173. {
  3174.     return (fclose(fp));
  3175. }
  3176.  
  3177. /* osagetc - get a character from an ascii file */
  3178. int osagetc(fp)
  3179.   FILE *fp;
  3180. {
  3181.     return (getc(fp));
  3182. }
  3183.  
  3184. /* osaputc - put a character to an ascii file */
  3185. int osaputc(ch,fp)
  3186.   int ch; FILE *fp;
  3187. {
  3188.     return (putc(ch,fp));
  3189. }
  3190.  
  3191. /* osbgetc - get a character from a binary file */
  3192. int osbgetc(fp)
  3193.   FILE *fp;
  3194. {
  3195.     return (getc(fp));
  3196. }
  3197.  
  3198. /* osbputc - put a character to a binary file */
  3199. int osbputc(ch,fp)
  3200.   int ch; FILE *fp;
  3201. {
  3202.     return (putc(ch,fp));
  3203. }
  3204.  
  3205. /* ostgetc - get a character from the terminal */
  3206. int ostgetc()
  3207. {
  3208.     int ch;
  3209.  
  3210.     /* check for a buffered character */
  3211.     if (lcount--)
  3212.         return (lbuf[lindex++]);
  3213.  
  3214.     /* get an input line */
  3215.     for (lcount = 0; ; )
  3216.         switch (ch = xgetc()) {
  3217.         case '\r':
  3218.                 lbuf[lcount++] = '\n';
  3219.                 xputc('\r'); xputc('\n'); lposition = 0;
  3220.                 if (tfp)
  3221.                     for (lindex = 0; lindex < lcount; ++lindex)
  3222.                         osaputc(lbuf[lindex],tfp);
  3223.                 lindex = 0; lcount--;
  3224.                 return (lbuf[lindex++]);
  3225.         case '\010':
  3226.         case '\177':
  3227.                 if (lcount) {
  3228.                     lcount--;
  3229.                     while (lposition > lpos[lcount]) {
  3230.                         xputc('\010'); xputc(' '); xputc('\010');
  3231.                         lposition--;
  3232.                     }
  3233.                 }
  3234.                 break;
  3235.         case '\032':
  3236.                 xflush();
  3237.                 return (EOF);
  3238.         default:
  3239.                 if (ch == '\t' || (ch >= 0x20 && ch < 0x7F)) {
  3240.                     lbuf[lcount] = ch;
  3241.                     lpos[lcount] = lposition;
  3242.                     if (ch == '\t')
  3243.                         do {
  3244.                             xputc(' ');
  3245.                         } while (++lposition & 7);
  3246.                     else {
  3247.                         xputc(ch); lposition++;
  3248.                     }
  3249.                     lcount++;
  3250.                 }
  3251.                 else {
  3252.                     xflush();
  3253.                     switch (ch) {
  3254.                     case '\002':        xlbreak("CTL-b",TRUE);  /* control-b */
  3255.                     case '\003':        xltoplevel();           /* control-c */
  3256.                     case '\007':        xlcleanup();            /* control-g */
  3257.                     case '\020':        xlcontinue();           /* control-p */
  3258.                     case '\032':        return (EOF);           /* control-z */
  3259.                     default:            return (ch);
  3260.                     }
  3261.                 }
  3262.         }
  3263. }
  3264.  
  3265. /* ostputc - put a character to the terminal */
  3266. ostputc(ch)
  3267.   int ch;
  3268. {
  3269.     /* check for control characters */
  3270.     oscheck();
  3271.  
  3272.     /* output the character */
  3273.     if (ch == '\n') {
  3274.         xputc('\r'); xputc('\n');
  3275.         lposition = 0;
  3276.     }
  3277.     else {
  3278.         xputc(ch);
  3279.         lposition++;
  3280.    }
  3281.  
  3282.    /* output the character to the transcript file */
  3283.    if (tfp)
  3284.         osaputc(ch,tfp);
  3285. }
  3286.  
  3287. /* oscheck - check for control characters during execution */
  3288. oscheck()
  3289. {
  3290.     int ch;
  3291.     if (ch = xcheck())
  3292.         switch (ch) {
  3293.         case '\002':    xflush(); xlbreak("BREAK",s_unbound); break;
  3294.         case '\003':    xflush(); xltoplevel(); break;
  3295.         }
  3296. }
  3297.  
  3298. /* osflush - flush the input line buffer */
  3299. osflush()
  3300. {
  3301.     lindex = lcount = 0;
  3302. }
  3303.  
  3304. /* ostell - get the current file position */
  3305. long ostell(fp)
  3306.   FILE *fp;
  3307. {
  3308.     return (ftell(fp));
  3309. }
  3310.  
  3311. /* osseek - set the current file position */
  3312. int osseek(fp,offset,whence)
  3313.   FILE *fp; long offset; int whence;
  3314. {
  3315.     return (fseek(fp,offset,whence));
  3316. }
  3317.  
  3318.  
  3319. /* xflush - flush the input line buffer */
  3320. static xflush()
  3321. {
  3322.     ostputc('\n');
  3323.     osflush();
  3324. }
  3325.  
  3326. /* xgetc - get a character from the terminal without echo */
  3327. static int xgetc()
  3328. {
  3329.     int ch;
  3330.     while ((ch = Crawio(0xFF)) == 0)
  3331.         ;
  3332.     return (ch & 0xFF);
  3333. }
  3334.  
  3335. /* xputc - put a character to the terminal */
  3336. static xputc(ch)
  3337.   int ch;
  3338. {
  3339.     Crawio(ch);
  3340. }
  3341.  
  3342. /* xcheck - check for a character */
  3343. static int xcheck()
  3344. {
  3345.     return (Crawio(0xFF));
  3346. }
  3347.  
  3348. /* file name extension table */
  3349. char *ext[] = { ".prg",".tos",".ttp",NULL };
  3350.  
  3351. /* xsystem - the built-in function 'system' */
  3352. LVAL xsystem()
  3353. {
  3354.     char *str,*p,cmd[100];
  3355.     int cmdlen,sts,i;
  3356.  
  3357.     /* get the command string */
  3358.     str = getstring(xlgastring());
  3359.     xllastarg();
  3360.  
  3361.     /* get the command name */
  3362.     for (p = cmd, cmdlen = 0; *str && !isspace(*str); ++cmdlen)
  3363.         *p++ = *str++;
  3364.     *p = '\0';
  3365.  
  3366.     /* skip spaces between the command name and the arguments */
  3367.     while (*str && isspace(*str))
  3368.         ++str;
  3369.  
  3370.     /* make a counted ascii argument list */
  3371.     for (p = &buf[1], buf[0] = '\0'; *str; ++buf[0])
  3372.         *p++ = *str++;
  3373.     *p = '\0';
  3374.  
  3375.     /* try each extension */
  3376.     for (i = 0; ext[i]; ++i) {
  3377.         strcpy(&cmd[cmdlen],ext[i]);
  3378.         if ((sts = Pexec(0,cmd,buf,"")) != -33)
  3379.             break;
  3380.     }
  3381.  
  3382.     /* return the completion status */
  3383.     return (cvfixnum((FIXTYPE)sts));
  3384. }
  3385.  
  3386. /* xgetkey - get a key from the keyboard */
  3387. LVAL xgetkey()
  3388. {
  3389.     xllastarg();
  3390.     return (cvfixnum((FIXTYPE)xgetc()));
  3391. }
  3392.  
  3393. /* ossymbols - lookup important symbols */
  3394. ossymbols()
  3395. {
  3396. }
  3397. argument list */
  3398.     for (p = &busrc/osdefs.h
  3399. 3400   6275
  3400.  
  3401.  
  3402.  
  3403. #ifdef MACINTOSH
  3404. extern LVAL xhidepen(),xshowpen(),xgetpen(),xpensize(),xpenmode();
  3405. extern LVAL xpenpat(),xpennormal(),xmoveto(),xmove(),xlineto(),xline();
  3406. extern LVAL xshowgraphics(),xhidegraphics(),xcleargraphics();
  3407. #endif
  3408.  
  3409. #ifdef MSDOS
  3410. extern LVAL xint86(),xinbyte(),xoutbyte(),xsystem(),xgetkey();
  3411. #endif
  3412.  
  3413. #ifdef UNIX
  3414. extern LVAL xsystem();
  3415. #endif
  3416. ϕ
  3417.  
  3418.  
  3419.  
  3420. achine specific functions */
  3421.  
  3422. #ifdef MACINTOSH
  3423. {       "HIDEPEN",                              xhidepen        },
  3424. {       "SHOWPEN",                              xshowpen        },
  3425. {       "GETPEN",                               xgetpen         },
  3426. {       "PENSIZE",                              xpensize        },
  3427. {       "PENMODE",                              xpenmode        },
  3428. {       "PENPAT",                               xpenpat         },
  3429. {       "PENNORMAL",                            xpennormal      },
  3430. {       "MOVETO",                               xmoveto         },
  3431. {       "MOVE",                                 xmove           },
  3432. {       "LINETO",                               xlineto         },
  3433. {       "LINE",                                 xline           },
  3434. {       "SHOW-GRAPHICS",                        xshowgraphics   },
  3435. {       "HIDE-GRAPHICS",                        xhidegraphics   },
  3436. {       "CLEAR-GRAPHICS",                       xcleargraphics  },
  3437. #endif
  3438.  
  3439. #ifdef MSDOS
  3440. {       "INT86",                                xint86          },
  3441. {       "INBYTE",                               xinbyte         },
  3442. {       "OUTBYTE",                              xoutbyte        },
  3443. {       "SYSTEM",                               xsystem         },
  3444. {       "GET-KEY",                              xgetkey         },
  3445. #endif
  3446.  
  3447. #ifdef UNIX
  3448. {       "SYSTEM",                               xsystem         },
  3449. #endif
  3450.  
  3451. ENMODE",                                xpenmode        },
  3452. {       "PENPAT",                               xpenpat         },
  3453. {       "PENNORMAL",                            xpennormal      },
  3454. {       "MOVETO",                               xmoveto         },
  3455. {       "MOVE",                                 xmove           },
  3456. {       "LINETO",                               xlineto         },
  3457. {       "LINE",                                 xline           },
  3458. {       "SHOW-GRAPHICS",                        xshowgraphics   },
  3459. {       "HIDE-GRAPHICS",                        xhidegraphics   },
  3460. {       "CLEAR-GRAPHICS",                       xcleargraphics  },
  3461. #endif
  3462.  
  3463. #ifdef Msrc/makefile.tos
  3464. 155
  3465.  
  3466.  
  3467. CFLAGS= -O -Datarist=1 -I. -I/users/gjh/cross-gcc/include
  3468.  
  3469. OBJ1 =xscheme.o xsdmem.o xsftab.o xsimage.o xsio.o xsobj.o \
  3470.       xsprint.o xsread.o xssym.o xsfun1.o xsfun2.o xsmath.o ststuff.o
  3471.  
  3472. OBJ2=xsinit.o xscom.o xsint.o
  3473.  
  3474. xscheme:        $(OBJ1) $(OBJ2)
  3475.         $(CC) $(CFLAGS) -o xscheme.ttp $(OBJ1) $(OBJ2) -lpml
  3476.  
  3477. $(OBJ1):        xscheme.h
  3478. $(OBJ2):        xscheme.h xsbcode.h
  3479. ∩π⑧
  3480.  
  3481.  
  3482.  
  3483.  
  3484. /*      Copyright (c) 1988, by David Michael Betz
  3485.         All Rights Reserved
  3486.         Permission is granted for unrestricted non-commercial use       */
  3487.  
  3488. #define OP_BRT          0x01    /* branch on true */
  3489. #define OP_BRF          0x02    /* branch on false */
  3490. #define OP_BR           0x03    /* branch unconditionally */
  3491. #define OP_LIT          0x04    /* load literal */
  3492. #define OP_GREF         0x05    /* global symbol value */
  3493. #define OP_GSET         0x06    /* set global symbol value */
  3494. #define OP_EREF         0x09    /* environment variable value */
  3495. #define OP_ESET         0x0A    /* set environment variable value */
  3496. #define OP_SAVE         0x0B    /* save a continuation */
  3497. #define OP_CALL         0x0C    /* call a function */
  3498. #define OP_RETURN       0x0D    /* return from a function */
  3499. #define OP_T            0x0E    /* load 'val' with t */
  3500. #define OP_NIL          0x0F    /* load 'val' with nil */
  3501. #define OP_PUSH         0x10    /* push the 'val' register */
  3502. #define OP_CLOSE        0x11    /* create a closure */
  3503.  
  3504. #define OP_FRAME        0x12    /* create a new enviroment frame */
  3505. #define OP_MVARG        0x13    /* move required argument to frame slot */
  3506. #define OP_MVOARG       0x14    /* move optional argument to frame slot */
  3507. #define OP_MVRARG       0x15    /* build rest argument and move to frame slot */
  3508. #define OP_ADROP        0x19    /* drop the rest of the arguments */
  3509. #define OP_ALAST        0x1A    /* make sure there are no more arguments */
  3510. #define OP_DELAY        0x1B    /* create a promise */
  3511.  
  3512. #define OP_AREF         0x1C    /* access a variable in an environment */
  3513. #define OP_ASET         0x1D    /* set a variable in an environment */
  3514.  
  3515. #define OP_ATOM         0x1E    /* atom predicate */
  3516. #define OP_EQ           0x1F    /* eq? predicate */
  3517. #define OP_NULL         0x20    /* null? (or not) predicate */
  3518. #define OP_CONS         0x21    /* cons */
  3519. #define OP_CAR          0x22    /* car */
  3520. #define OP_CDR          0x23    /* cdr */
  3521. #define OP_SETCAR       0x24    /* set-car! */
  3522. #define OP_SETCDR       0x25    /* set-cdr! */
  3523.  
  3524. #define OP_ADD          0x40    /* add two numeric expressions */
  3525. #define OP_SUB          0x41    /* subtract two numeric expressions */
  3526. #define OP_MUL          0x42    /* multiply two numeric expressions */
  3527. #define OP_QUO          0x43    /* divide two integer expressions */
  3528. #define OP_LSS          0x44    /* less than */
  3529. #define OP_EQL          0x45    /* equal to */
  3530. #define OP_GTR          0x46    /* greater than */
  3531. e OP_CONS               0x21    /* cons */
  3532. #define OP_CAR          0x22    /* car */
  3533. #define OP_CDR          0x23    /* cdr */
  3534. #define OP_SETCAR       0x24    /* set-car! */
  3535. #define OP_SETCDR       0x25    /* set-cdr! */
  3536.  
  3537. #define OP_ADD          0x40    /* add two numeric expressions */
  3538. #define OP_SUB          0x41    /* subtract two numeric expressions */
  3539. #define OP_MUL          0x42    /* multiply two numeric expressions */
  3540. #define OP_QUO          0x43    /* divide two integer expressions */
  3541. #define OP_LSS          0x44    /* less than */
  3542. #definsrc/xscheme.c
  3543. 2
  3544.  
  3545.  
  3546. /*      Copyright (c) 1988, by David Michael Betz
  3547.         All Rights Reserved
  3548.         Permission is granted for unrestricted non-commercial use       */
  3549.  
  3550. #include "xscheme.h"
  3551.  
  3552. /* the program banner */
  3553. #define BANNER  "XScheme - Version 0.22"
  3554.  
  3555. /* global variables */
  3556. jmp_buf top_level;
  3557. int clargc;     /* command line argument count */
  3558. char **clargv;  /* array of command line arguments */
  3559.  
  3560. /* trace file pointer */
  3561. FILE *tfp=NULL;
  3562.  
  3563. /* external variables */
  3564. extern LVAL xlfun,xlenv,xlval;
  3565. extern LVAL s_stdin,s_stdout,s_stderr,s_unbound;
  3566. extern int trace;
  3567.  
  3568. /* main - the main routine */
  3569. main(argc,argv)
  3570.   int argc; char *argv[];
  3571. {
  3572.     int src,dst;
  3573.     LVAL code;
  3574.     char *p;
  3575.     
  3576.     /* process the arguments */
  3577.     for (src = dst = 1, clargv = argv, clargc = 1; src < argc; ++src) {
  3578.  
  3579.         /* handle options */
  3580.         if (argv[src][0] == '-') {
  3581.             for (p = &argv[src][1]; *p != '\0'; )
  3582.                 switch (*p++) {
  3583.                 case 't':               /* root directory */
  3584.                     trace = TRUE;
  3585.                     break;
  3586.                 default:
  3587.                     usage();
  3588.                 }
  3589.         }
  3590.  
  3591.         /* handle a filename */
  3592.         else {
  3593.             argv[dst++] = argv[src];
  3594.             ++clargc;
  3595.         }
  3596.     }
  3597.  
  3598.     /* setup an initialization error handler */
  3599.     if (setjmp(top_level))
  3600.         exit(1);
  3601.  
  3602.     /* initialize */
  3603.     osinit(BANNER);
  3604.     
  3605.     /* restore the default workspace, otherwise create a new one */
  3606.     if (!xlirestore("xscheme.wks"))
  3607.         xlinitws(5000);
  3608.  
  3609.     /* do the initialization code first */
  3610.     code = xlenter("*INITIALIZE*");
  3611.     code = (boundp(code) ? getvalue(code) : NIL);
  3612.  
  3613.     /* trap errors */
  3614.     if (setjmp(top_level)) {
  3615.         code = xlenter("*TOPLEVEL*");
  3616.         code = (boundp(code) ? getvalue(code) : NIL);
  3617.         xlfun = xlenv = xlval = NIL;
  3618.         xlsp = xlstktop;
  3619.     }
  3620.  
  3621.     /* execute the main loop */
  3622.     if (code != NIL)
  3623.         xlexecute(code);
  3624.     wrapup();
  3625. }
  3626.  
  3627. usage()
  3628. {
  3629.     info("usage: xscheme [-t]\n");
  3630.     exit(1);
  3631. }
  3632.  
  3633. xlload() {}
  3634. xlcontinue() {}
  3635. xlbreak() { xltoplevel(); }
  3636. xlcleanup() {}
  3637.  
  3638. /* xltoplevel - return to the top level */
  3639. xltoplevel()
  3640. {
  3641.     stdputstr("[ back to top level ]\n");
  3642.     longjmp(top_level,1);
  3643. }
  3644.  
  3645. /* xlfail - report an error */
  3646. xlfail(msg)
  3647.   char *msg;
  3648. {
  3649.     xlerror(msg,s_unbound);
  3650. }
  3651.  
  3652. /* xlerror - report an error */
  3653. xlerror(msg,arg)
  3654.   char *msg; LVAL arg;
  3655. {
  3656.     /* display the error message */
  3657.     errputstr("Error: ");
  3658.     errputstr(msg);
  3659.     errputstr("\n");
  3660.     
  3661.     /* print the argument on a separate line */
  3662.     if (arg != s_unbound) {
  3663.         errputstr("  ");
  3664.         errprint(arg);
  3665.     }
  3666.     
  3667.     /* print the function where the error occurred */
  3668.     errputstr("happened in: ");
  3669.     errprint(xlfun);
  3670.  
  3671.     /* call the handler */
  3672.     callerrorhandler();
  3673. }
  3674.  
  3675. /* callerrorhandler - call the error handler */
  3676. callerrorhandler()
  3677. {
  3678.     extern jmp_buf bc_dispatch;
  3679.     
  3680.     /* invoke the error handler */
  3681.     if (xlval = getvalue(xlenter("*ERROR-HANDLER*"))) {
  3682.         oscheck();      /* an opportunity to break out of a bad handler */
  3683.         check(2);
  3684.         push(xlenv);
  3685.         push(xlfun);
  3686.         xlargc = 2;
  3687.         xlapply();
  3688.         longjmp(bc_dispatch,1);
  3689.     }
  3690.  
  3691.     /* no handler, just reset back to the top level */
  3692.     longjmp(top_level,1);
  3693. }
  3694.  
  3695. /* xlabort - print an error message and abort */
  3696. xlabort(msg)
  3697.   char *msg;
  3698. {
  3699.     /* display the error message */
  3700.     errputstr("Abort: ");
  3701.     errputstr(msg);
  3702.     errputstr("\n");
  3703.     
  3704.     /* print the function where the error occurred */
  3705.     errputstr("happened in: ");
  3706.     errprint(xlfun);
  3707.  
  3708.     /* reset back to the top level */
  3709.     oscheck();  /* an opportunity to break out */
  3710.     longjmp(top_level,1);
  3711. }
  3712.  
  3713. /* xlfatal - print a fatal error message and exit */
  3714. xlfatal(fmt,a1,a2,a3,a4)
  3715.   char *fmt;
  3716. {
  3717.     char buf[100];
  3718.     sprintf(buf,fmt,a1,a2,a3,a4);
  3719.     oserror(buf);
  3720.     exit(1);
  3721. }
  3722.  
  3723. /* info - display debugging information */
  3724. info(fmt,a1,a2,a3,a4)
  3725.   char *fmt;
  3726. {
  3727.     char buf[100],*p;
  3728.     sprintf(buf,fmt,a1,a2,a3,a4);
  3729.     for (p = buf; *p != '\0'; )
  3730.         ostputc(*p++);
  3731. }
  3732.  
  3733. /* wrapup - clean up and exit to the operating system */
  3734. wrapup()
  3735. {
  3736.     if (tfp)
  3737.         osclose(tfp);
  3738.     osfinish();
  3739.     exit(0);
  3740. }
  3741. (top_level,1);
  3742. }
  3743.  
  3744. /* xlfatal - print a fatal error message and exit */
  3745. xlfatal(fmt,a1,a2,a3,a4)
  3746.   char *fmt;
  3747. {
  3748.     char buf[100];
  3749.     sprintf(buf,fmt,a1,a2,a3,a4);
  3750.     oserror(buf)src/xscheme.h
  3751. 1104   6504
  3752.  
  3753.  
  3754. /*      Copyright (c) 1988, by David Michael Betz
  3755.         All Rights Reserved
  3756.         Permission is granted for unrestricted non-commercial use       */
  3757.  
  3758.  
  3759. /* system specific definitions */
  3760. /* #define _TURBOC_ */
  3761. #define UNIX
  3762.  
  3763. #include <stdio.h>
  3764. #include <ctype.h>
  3765. #include <setjmp.h>
  3766.  
  3767. /* FORWARD      type of a forward declaration () */
  3768. /* LOCAL        type of a local function (static) */
  3769. /* AFMT         printf format for addresses ("%x") */
  3770. /* OFFTYPE      number the size of an address (int) */
  3771. /* FIXTYPE      data type for fixed point numbers (long) */
  3772. /* ITYPE        fixed point input conversion routine type (long atol()) */
  3773. /* ICNV         fixed point input conversion routine (atol) */
  3774. /* IFMT         printf format for fixed point numbers ("%ld") */
  3775. /* FLOTYPE      data type for floating point numbers (float) */
  3776. /* FFMT         printf format for floating point numbers (%.15g) */
  3777.  
  3778. /* for the Lightspeed C compiler - Macintosh */
  3779. #ifdef LSC
  3780. #define AFMT            "%lx"
  3781. #define OFFTYPE         long
  3782. #define NIL             (void *)0
  3783. #define MACINTOSH
  3784. #endif
  3785.  
  3786. /* for the UNIX System V C compiler */
  3787. #ifdef UNIX
  3788. #endif
  3789.  
  3790. /* for the Aztec C compiler - Amiga */
  3791. #ifdef AZTEC_AMIGA
  3792. #define AFMT            "%lx"
  3793. #define OFFTYPE         long
  3794. #endif
  3795.  
  3796. /* for the Mark Williams C compiler - Atari ST */
  3797. #ifdef MWC
  3798. #define AFMT            "%lx"
  3799. #define OFFTYPE         long
  3800. #endif
  3801.  
  3802. /* for the Microsoft C 5.0 compiler */
  3803. #ifdef MSC
  3804. #define AFMT            "%lx"
  3805. #define OFFTYPE         long
  3806. #define INSEGMENT(n,s)  (((OFFTYPE)(n) >> 16) == ((OFFTYPE)(s) >> 16))
  3807. #define VCOMPARE(f,s,t) ((LVAL huge *)(f) + (s) <= (LVAL huge *)(t))
  3808. /* #define MSDOS -- MSC 5.0 defines this automatically */
  3809. #endif
  3810.  
  3811. /* for the Turbo C compiler */
  3812. #ifdef _TURBOC_
  3813. #define AFMT            "%lx"
  3814. #define OFFTYPE         long
  3815. #define INSEGMENT(n,s)  (((OFFTYPE)(n) >> 16) == ((OFFTYPE)(s) >> 16))
  3816. #define VCOMPARE(f,s,t) ((LVAL huge *)(f) + (s) <= (LVAL huge *)(t))
  3817. #define MSDOS
  3818. #endif
  3819.  
  3820. /* size of each type of memory segment */
  3821. #ifndef NSSIZE
  3822. #define NSSIZE  4000    /* number of nodes per node segment */
  3823. #endif
  3824. #ifndef VSSIZE
  3825. #define VSSIZE  10000   /* number of LVAL's per vector segment */
  3826. #endif
  3827.  
  3828. /* default important definitions */
  3829. #ifndef FORWARD
  3830. #define FORWARD
  3831. #endif
  3832. #ifndef LOCAL
  3833. #define LOCAL           static
  3834. #endif
  3835. #ifndef AFMT
  3836. #define AFMT            "%x"
  3837. #endif
  3838. #ifndef OFFTYPE
  3839. #define OFFTYPE         int
  3840. #endif
  3841. #ifndef FIXTYPE
  3842. #define FIXTYPE         long
  3843. #endif
  3844. #ifndef ITYPE
  3845. #define ITYPE           long atol()
  3846. #endif
  3847. #ifndef ICNV
  3848. #define ICNV(n)         atol(n)
  3849. #endif
  3850. #ifndef IFMT
  3851. #define IFMT            "%ld"
  3852. #endif
  3853. #ifndef FLOTYPE
  3854. #define FLOTYPE         double
  3855. #endif
  3856. #ifndef FFMT
  3857. #define FFMT            "%.15g"
  3858. #endif
  3859. #ifndef SFIXMIN
  3860. #define SFIXMIN         -1048576
  3861. #define SFIXMAX         1048575
  3862. #endif
  3863. #ifndef INSEGMENT
  3864. #define INSEGMENT(n,s)  ((n) >= &(s)->ns_data[0] \
  3865.                       && (n) <  &(s)->ns_data[0] + (s)->ns_size)
  3866. #endif
  3867. #ifndef VCOMPARE
  3868. #define VCOMPARE(f,s,t) ((f) + (s) <= (t))
  3869. #endif
  3870.  
  3871. /* useful definitions */
  3872. #define TRUE    1
  3873. #define FALSE   0
  3874. #ifndef NIL
  3875. #define NIL     (LVAL)0
  3876. #endif
  3877.  
  3878. /* program limits */
  3879. #define STRMAX          100             /* maximum length of a string constant */
  3880. #define HSIZE           199             /* symbol hash table size */
  3881. #define SAMPLE          100             /* control character sample rate */
  3882.  
  3883. /* stack manipulation macros */
  3884. #define check(n)        { if (xlsp - (n) < xlstkbase) xlstkover(); }
  3885. #define cpush(v)        { if (xlsp > xlstkbase) push(v); else xlstkover(); }
  3886. #define push(v)         (*--xlsp = (v))
  3887. #define pop()           (*xlsp++)
  3888. #define top()           (*xlsp)
  3889. #define settop(v)       (*xlsp = (v))
  3890. #define drop(n)         (xlsp += (n))
  3891.  
  3892. /* argument list parsing macros */
  3893. #define xlgetarg()      (testarg(nextarg()))
  3894. #define xllastarg()     {if (xlargc != 0) xltoomany();}
  3895. #define xlpoprest()     {xlsp += xlargc;}
  3896. #define testarg(e)      (moreargs() ? (e) : xltoofew())
  3897. #define typearg(tp)     (tp(*xlsp) ? nextarg() : xlbadtype(*xlsp))
  3898. #define nextarg()       (--xlargc, *xlsp++)
  3899. #define moreargs()      (xlargc > 0)
  3900.  
  3901. /* macros to get arguments of a particular type */
  3902. #define xlgacons()      (testarg(typearg(consp)))
  3903. #define xlgalist()      (testarg(typearg(listp)))
  3904. #define xlgasymbol()    (testarg(typearg(symbolp)))
  3905. #define xlgastring()    (testarg(typearg(stringp)))
  3906. #define xlgaobject()    (testarg(typearg(objectp)))
  3907. #define xlgafixnum()    (testarg(typearg(fixp)))
  3908. #define xlganumber()    (testarg(typearg(numberp)))
  3909. #define xlgachar()      (testarg(typearg(charp)))
  3910. #define xlgavector()    (testarg(typearg(vectorp)))
  3911. #define xlgaport()      (testarg(typearg(portp)))
  3912. #define xlgaiport()     (testarg(typearg(iportp)))
  3913. #define xlgaoport()     (testarg(typearg(oportp)))
  3914. #define xlgaclosure()   (testarg(typearg(closurep)))
  3915. #define xlgaenv()       (testarg(typearg(envp)))
  3916.  
  3917. /* node types */
  3918. #define FREE            0
  3919. #define CONS            1
  3920. #define SYMBOL          2
  3921. #define FIXNUM          3
  3922. #define FLONUM          4
  3923. #define STRING          5
  3924. #define OBJECT          6
  3925. #define PORT            7
  3926. #define VECTOR          8
  3927. #define CLOSURE         9
  3928. #define METHOD          10
  3929. #define CODE            11
  3930. #define SUBR            12
  3931. #define XSUBR           13
  3932. #define CSUBR           14
  3933. #define CONTINUATION    15
  3934. #define CHAR            16
  3935. #define PROMISE         17
  3936. #define ENV             18
  3937.  
  3938. /* node flags */
  3939. #define MARK            1
  3940. #define LEFT            2
  3941.  
  3942. /* port flags */
  3943. #define PF_INPUT        1
  3944. #define PF_OUTPUT       2
  3945. #define PF_BINARY       4
  3946.  
  3947. /* new node access macros */
  3948. #define ntype(x)        ((OFFTYPE)(x) & 1 ? FIXNUM : (x)->n_type)
  3949.  
  3950. /* macro to determine if a non-nil value is a pointer */
  3951. #define ispointer(x)    (((OFFTYPE)(x) & 1) == 0)
  3952.  
  3953. /* type predicates */                          
  3954. #define atom(x)         ((x) == NIL || ntype(x) != CONS)
  3955. #define null(x)         ((x) == NIL)
  3956. #define listp(x)        ((x) == NIL || ntype(x) == CONS)
  3957. #define numberp(x)      ((x) && ntype(x) == FIXNUM || ntype(x) == FLONUM)
  3958. #define boundp(x)       (getvalue(x) != s_unbound)
  3959. #define iportp(x)       (portp(x) && (getpflags(x) & PF_INPUT) != 0)
  3960. #define oportp(x)       (portp(x) && (getpflags(x) & PF_OUTPUT) != 0)
  3961.  
  3962. /* basic type predicates */                            
  3963. #define consp(x)        ((x) && ntype(x) == CONS)
  3964. #define stringp(x)      ((x) && ntype(x) == STRING)
  3965. #define symbolp(x)      ((x) && ntype(x) == SYMBOL)
  3966. #define portp(x)        ((x) && ntype(x) == PORT)
  3967. #define objectp(x)      ((x) && ntype(x) == OBJECT)
  3968. #define fixp(x)         ((x) && ntype(x) == FIXNUM)
  3969. #define floatp(x)       ((x) && ntype(x) == FLONUM)
  3970. #define vectorp(x)      ((x) && ntype(x) == VECTOR)
  3971. #define closurep(x)     ((x) && ntype(x) == CLOSURE)
  3972. #define codep(x)        ((x) && ntype(x) == CODE)
  3973. #define methodp(x)      ((x) && ntype(x) == METHOD)
  3974. #define subrp(x)        ((x) && ntype(x) == SUBR)
  3975. #define xsubrp(x)       ((x) && ntype(x) == XSUBR)
  3976. #define charp(x)        ((x) && ntype(x) == CHAR)
  3977. #define promisep(x)     ((x) && ntype(x) == PROMISE)
  3978. #define envp(x)         ((x) && ntype(x) == ENV)
  3979. #define booleanp(x)     ((x) == NIL || ntype(x) == BOOLEAN)
  3980.  
  3981. /* vector update macro
  3982.    This is necessary because the memory pointed to by the n_vdata field
  3983.    of a vector object can move during a garbage collection.  This macro
  3984.    guarantees that evaluation happens in the right order.
  3985. */
  3986. #define vupdate(x,i,v)  { LVAL vutmp=(v); (x)->n_vdata[i] = vutmp; }
  3987.  
  3988. /* cons access macros */
  3989. #define car(x)          ((x)->n_car)
  3990. #define cdr(x)          ((x)->n_cdr)
  3991. #define rplaca(x,y)     ((x)->n_car = (y))
  3992. #define rplacd(x,y)     ((x)->n_cdr = (y))
  3993.  
  3994. /* symbol access macros */
  3995. #define getvalue(x)      ((x)->n_vdata[0])
  3996. #define setvalue(x,v)    vupdate(x,0,v)
  3997. #define getpname(x)      ((x)->n_vdata[1])
  3998. #define setpname(x,v)    vupdate(x,1,v)
  3999. #define getplist(x)      ((x)->n_vdata[2])
  4000. #define setplist(x,v)    vupdate(x,2,v)
  4001. #define SYMSIZE         3
  4002.  
  4003. /* vector access macros */
  4004. #define getsize(x)      ((x)->n_vsize)
  4005. #define getelement(x,i) ((x)->n_vdata[i])
  4006. #define setelement(x,i,v) vupdate(x,i,v)
  4007.  
  4008. /* object access macros */
  4009. #define getclass(x)     ((x)->n_vdata[1])
  4010. #define setclass(x,v)   vupdate(x,1,v)
  4011. #define getivar(x,i)    ((x)->n_vdata[i])
  4012. #define setivar(x,i,v)  vupdate(x,i,v)
  4013.  
  4014. /* promise access macros */
  4015. #define getpproc(x)     ((x)->n_car)
  4016. #define setpproc(x,v)   ((x)->n_car = (v))
  4017. #define getpvalue(x)    ((x)->n_cdr)
  4018. #define setpvalue(x,v)  ((x)->n_cdr = (v))
  4019.  
  4020. /* closure access macros */
  4021. #define getcode(x)      ((x)->n_car)
  4022. #define getenv(x)       ((x)->n_cdr)
  4023.  
  4024. /* code access macros */
  4025. #define getbcode(x)             ((x)->n_vdata[0])
  4026. #define setbcode(x,v)           vupdate(x,0,v)
  4027. #define getcname(x)             ((x)->n_vdata[1])
  4028. #define setcname(x,v)           vupdate(x,1,v)
  4029. #define getvnames(x)            ((x)->n_vdata[2])
  4030. #define setvnames(x,v)          vupdate(x,2,v)
  4031. #define FIRSTLIT                3
  4032.  
  4033. /* fixnum/flonum/character access macros */
  4034. #define getfixnum(x)    ((OFFTYPE)(x) & 1 ? getsfixnum(x) : (x)->n_int)
  4035. #define getflonum(x)    ((x)->n_flonum)
  4036. #define getchcode(x)    ((x)->n_chcode)
  4037.  
  4038. /* small fixnum access macros */
  4039. #define cvsfixnum(x)    ((LVAL)(((OFFTYPE)x << 1) | 1))
  4040. #define getsfixnum(x)   ((FIXTYPE)((OFFTYPE)(x) >> 1))
  4041.  
  4042. /* string access macros */
  4043. #define getstring(x)    ((unsigned char *)(x)->n_vdata)
  4044. #define getslength(x)   ((x)->n_vsize)
  4045.  
  4046. /* iport/oport access macros */
  4047. #define getfile(x)      ((x)->n_fp)
  4048. #define setfile(x,v)    ((x)->n_fp = (v))
  4049. #define getsavech(x)    ((x)->n_savech)
  4050. #define setsavech(x,v)  ((x)->n_savech = (v))
  4051. #define getpflags(x)    ((x)->n_pflags)
  4052. #define setpflags(x,v)  ((x)->n_pflags = (v))
  4053.  
  4054. /* subr access macros */
  4055. #define getsubr(x)      ((x)->n_subr)
  4056. #define getoffset(x)    ((x)->n_offset)
  4057.  
  4058. /* list node */
  4059. #define n_car           n_info.n_xlist.xl_car
  4060. #define n_cdr           n_info.n_xlist.xl_cdr
  4061.  
  4062. /* integer node */
  4063. #define n_int           n_info.n_xint.xi_int
  4064.  
  4065. /* flonum node */
  4066. #define n_flonum        n_info.n_xflonum.xf_flonum
  4067.  
  4068. /* character node */
  4069. #define n_chcode        n_info.n_xchar.xc_chcode
  4070.  
  4071. /* string node */
  4072. #define n_str           n_info.n_xstr.xst_str
  4073. #define n_strlen        n_info.n_xstr.xst_length
  4074.  
  4075. /* file pointer node */
  4076. #define n_fp            n_info.n_xfptr.xf_fp
  4077. #define n_savech        n_info.n_xfptr.xf_savech
  4078. #define n_pflags        n_info.n_xfptr.xf_pflags
  4079.  
  4080. /* vector/object node */
  4081. #define n_vsize         n_info.n_xvect.xv_size
  4082. #define n_vdata         n_info.n_xvect.xv_data
  4083.  
  4084. /* subr node */
  4085. #define n_subr          n_info.n_xsubr.xs_subr
  4086. #define n_offset        n_info.n_xsubr.xs_offset
  4087.  
  4088. /* node structure */
  4089. typedef struct node {
  4090.     char n_type;                /* type of node */
  4091.     char n_flags;               /* flag bits */
  4092.     union ninfo {               /* value */
  4093.         struct xlist {          /* list node (cons) */
  4094.             struct node *xl_car;        /* the car pointer */
  4095.             struct node *xl_cdr;        /* the cdr pointer */
  4096.         } n_xlist;
  4097.         struct xint {           /* integer node */
  4098.             FIXTYPE xi_int;             /* integer value */
  4099.         } n_xint;
  4100.         struct xflonum {        /* flonum node */
  4101.             FLOTYPE xf_flonum;          /* flonum value */
  4102.         } n_xflonum;
  4103.         struct xchar {          /* character node */
  4104.             int xc_chcode;              /* character code */
  4105.         } n_xchar;
  4106.         struct xstr {           /* string node */
  4107.             int xst_length;             /* string length */
  4108.             unsigned char *xst_str;     /* string pointer */
  4109.         } n_xstr;
  4110.         struct xfptr {          /* file pointer node */
  4111.             FILE *xf_fp;                /* the file pointer */
  4112.             short xf_savech;            /* lookahead character for input files */
  4113.             short xf_pflags;            /* port flags */
  4114.         } n_xfptr;
  4115.         struct xvect {          /* vector node */
  4116.             int xv_size;                /* vector size */
  4117.             struct node **xv_data;      /* vector data */
  4118.         } n_xvect;
  4119.         struct xsubr {          /* subr/fsubr node */
  4120.             struct node *(*xs_subr)();  /* function pointer */
  4121.             int xs_offset;              /* offset into funtab */
  4122.         } n_xsubr;
  4123.     } n_info;
  4124. } NODE,*LVAL;
  4125.  
  4126. /* memory allocator definitions */
  4127.  
  4128. /* macros to compute the size of a segment */
  4129. #define nsegsize(n) (sizeof(NSEGMENT)+((n)-1)*sizeof(struct node))
  4130. #define vsegsize(n) (sizeof(VSEGMENT)+((n)-1)*sizeof(LVAL))
  4131.  
  4132. /* macro to convert a byte size to a word size */
  4133. #define btow_size(n)    (((n) + sizeof(LVAL) - 1) / sizeof(LVAL))
  4134.  
  4135. /* node segment structure */
  4136. typedef struct nsegment {
  4137.     struct nsegment *ns_next;   /* next node segment */
  4138.     unsigned int ns_size;       /* number of nodes in this segment */
  4139.     struct node ns_data[1];     /* segment data */
  4140. } NSEGMENT;
  4141.  
  4142. /* vector segment structure */
  4143. typedef struct vsegment {
  4144.     struct vsegment *vs_next;   /* next vector segment */
  4145.     LVAL *vs_free;              /* next free location in this segment */
  4146.     LVAL *vs_top;               /* top of segment (plus one) */
  4147.     LVAL vs_data[1];            /* segment data */
  4148. } VSEGMENT;
  4149.  
  4150. /* function definition structure */
  4151. typedef struct {
  4152.     char *fd_name;      /* function name */
  4153.     LVAL (*fd_subr)();  /* function entry point */
  4154. } FUNDEF;
  4155.  
  4156. /* external variables */
  4157. extern LVAL *xlstkbase;         /* base of value stack */
  4158. extern LVAL *xlstktop;          /* top of value stack */
  4159. extern LVAL *xlsp;              /* value stack pointer */
  4160. extern int xlargc;              /* argument count for current call */
  4161.  
  4162. /* external routine declarations */
  4163. extern LVAL cons();             /* (cons x y) */
  4164. extern LVAL xlenter();          /* enter a symbol */
  4165. extern LVAL xlgetprop();        /* get the value of a property */
  4166. extern LVAL cvsymbol();         /* convert a string to a symbol */
  4167. extern LVAL cvstring();         /* convert a string */
  4168. extern LVAL cvfixnum();         /* convert a fixnum */
  4169. extern LVAL cvflonum();         /* convert a flonum */
  4170. extern LVAL cvchar();           /* convert a character */
  4171. extern LVAL cvclosure();        /* convert code and an env to a closure */
  4172. extern LVAL cvmethod();         /* convert code and an env to a method */
  4173. extern LVAL cvsubr();           /* convert a function into a subr */
  4174. extern LVAL cvport();           /* convert a file pointer to an input port */
  4175. extern LVAL cvpromise();        /* convert a procedure to a promise */
  4176. extern LVAL newstring();        /* create a new string */
  4177. extern LVAL newobject();        /* create a new object */
  4178. extern LVAL newvector();        /* create a new vector */
  4179. extern LVAL newcode();          /* create a new code object */
  4180. extern LVAL newcontinuation();  /* create a new continuation object */
  4181. extern LVAL newframe();         /* create a new environment frame */
  4182. extern LVAL newnode();          /* create a new node */
  4183. extern LVAL xltoofew();         /* report "too few arguments" */
  4184. extern LVAL xlbadtype();        /* report "wrong argument type" */
  4185. extern LVAL curinput();         /* get the current input port */
  4186. extern LVAL curoutput();        /* get the current output port */
  4187. src/xscom.c
  4188.  
  4189.  
  4190.  
  4191. /*      Copyright (c) 1988, by David Michael Betz
  4192.         All Rights Reserved
  4193.         Permission is granted for unrestricted non-commercial use       */
  4194.  
  4195. #include "xscheme.h"
  4196. #include "xsbcode.h"
  4197.  
  4198. /* size of code buffer */
  4199. #define CMAX    4000
  4200.  
  4201. /* continuation types */
  4202. #define C_RETURN        -1
  4203. #define C_NEXT          -2
  4204.  
  4205. /* macro to check for a lambda list keyword */
  4206. #define lambdakey(x)    ((x) == lk_optional || (x) == lk_rest)
  4207.  
  4208. /* external variables */
  4209. extern LVAL lk_optional,lk_rest,true_lval;  /* BCB global rename true ==> true_lval */
  4210.  
  4211. /* local variables */
  4212. static LVAL info;               /* compiler info */
  4213.  
  4214. /* code buffer */
  4215. static unsigned char cbuff[CMAX];       /* base of code buffer */
  4216. static int cbase;                       /* base for current function */
  4217. static int cptr;                        /* code buffer pointer */
  4218.  
  4219. /* forward declarations */
  4220. int do_define(),do_set(),do_quote(),do_lambda(),do_delay();
  4221. int do_let(),do_letrec(),do_letstar(),do_cond(),do_and(),do_or();
  4222. int do_if(),do_begin(),do_while(),do_access();
  4223. LVAL make_code_object();
  4224.  
  4225. /* integrable function table */
  4226. typedef struct { char *nt_name; int nt_code,nt_args; } NTDEF;
  4227. static NTDEF *nptr,ntab[] = {
  4228.         "ATOM",                 OP_ATOM,        1,
  4229.         "EQ?",                  OP_EQ,          2,
  4230.         "NULL?",                OP_NULL,        1,
  4231.         "NOT",                  OP_NULL,        1,
  4232.         "CONS",                 OP_CONS,        2,
  4233.         "CAR",                  OP_CAR,         1,
  4234.         "CDR",                  OP_CDR,         1,
  4235.         "SET-CAR!",             OP_SETCAR,      2,
  4236.         "SET-CDR!",             OP_SETCDR,      2,
  4237.         "+",                    OP_ADD,         -2,
  4238.         "-",                    OP_SUB,         -2,
  4239.         "*",                    OP_MUL,         -2,
  4240.         "QUOTIENT",             OP_QUO,         -2,
  4241.         "<",                    OP_LSS,         -2,
  4242.         "=",                    OP_EQL,         -2,
  4243.         ">",                    OP_GTR,         -2,
  4244.         0
  4245. };
  4246.  
  4247. /* special form table */
  4248. typedef struct { char *ft_name; int (*ft_fcn)(); } FTDEF;
  4249. static FTDEF ftab[] = {
  4250.         "QUOTE",        do_quote,
  4251.         "LAMBDA",       do_lambda,
  4252.         "DELAY",        do_delay,
  4253.         "LET",          do_let,
  4254.         "LET*",         do_letstar,
  4255.         "LETREC",       do_letrec,
  4256.         "DEFINE",       do_define,
  4257.         "SET!",         do_set,
  4258.         "IF",           do_if,
  4259.         "COND",         do_cond,
  4260.         "BEGIN",        do_begin,
  4261.         "SEQUENCE",     do_begin,
  4262.         "AND",          do_and,
  4263.         "OR",           do_or,
  4264.         "WHILE",        do_while,
  4265.         "ACCESS",       do_access,
  4266.         0
  4267. };
  4268.  
  4269. /* xlcompile - compile an expression */
  4270. LVAL xlcompile(expr,ctenv)
  4271.   LVAL expr,ctenv;
  4272. {
  4273.     /* initialize the compile time environment */
  4274.     info = cons(NIL,NIL); cpush(info);
  4275.     rplaca(info,newframe(ctenv,1));
  4276.     rplacd(info,cons(NIL,NIL));
  4277.  
  4278.     /* setup the base of the code for this function */
  4279.     cbase = cptr = 0;
  4280.  
  4281.     /* setup the entry code */
  4282.     putcbyte(OP_FRAME);
  4283.     putcbyte(1);
  4284.  
  4285.     /* compile the expression */
  4286.     do_expr(expr,C_RETURN);
  4287.  
  4288.     /* build the code object */
  4289.     settop(make_code_object(NIL));
  4290.     return (pop());
  4291. }
  4292.  
  4293. /* xlfunction - compile a function */
  4294. LVAL xlfunction(fun,fargs,body,ctenv)
  4295.   LVAL fun,fargs,body,ctenv;
  4296. {
  4297.     /* initialize the compile time environment */
  4298.     info = cons(NIL,NIL); cpush(info);
  4299.     rplaca(info,newframe(ctenv,1));
  4300.     rplacd(info,cons(NIL,NIL));
  4301.  
  4302.     /* setup the base of the code for this function */
  4303.     cbase = cptr = 0;
  4304.  
  4305.     /* compile the lambda list and the function body */
  4306.     parse_lambda_list(fargs,body);
  4307.     do_begin(body,C_RETURN);
  4308.  
  4309.     /* build the code object */
  4310.     settop(make_code_object(fun));
  4311.     return (pop());
  4312. }
  4313.  
  4314. /* do_expr - compile an expression */
  4315. LOCAL do_expr(expr,cont)
  4316.   LVAL expr; int cont;
  4317. {
  4318.     LVAL fun;
  4319.     if (consp(expr)) {
  4320.         fun = car(expr);
  4321.         if (!symbolp(fun) || (!in_ntab(expr,cont) && !in_ftab(expr,cont)))
  4322.             do_call(expr,cont);
  4323.     }
  4324.     else if (symbolp(expr))
  4325.         do_identifier(expr,cont);
  4326.     else
  4327.         do_literal(expr,cont);
  4328. }
  4329.  
  4330. /* in_ntab - check for a function in ntab */
  4331. LOCAL int in_ntab(expr,cont)
  4332.   LVAL expr; int cont;
  4333. {
  4334.     unsigned char *pname;
  4335.     pname = getstring(getpname(car(expr)));
  4336.     for (nptr = ntab; nptr->nt_name; ++nptr)
  4337.         if (strcmp(pname,nptr->nt_name) == 0) {
  4338.             do_nary(nptr->nt_code,nptr->nt_args,expr,cont);
  4339.             return (TRUE);
  4340.         }
  4341.     return (FALSE);
  4342. }
  4343.  
  4344. /* in_ftab - check for a function in ftab */
  4345. LOCAL int in_ftab(expr,cont)
  4346.   LVAL expr; int cont;
  4347. {
  4348.     unsigned char *pname;
  4349.     FTDEF *fptr;
  4350.     pname = getstring(getpname(car(expr)));
  4351.     for (fptr = ftab; fptr->ft_name; ++fptr)
  4352.         if (strcmp(pname,fptr->ft_name) == 0) {
  4353.             (*fptr->ft_fcn)(cdr(expr),cont);
  4354.             return (TRUE);
  4355.         }
  4356.     return (FALSE);
  4357. }
  4358.  
  4359. /* do_define - handle the (DEFINE ... ) expression */
  4360. LOCAL do_define(form,cont)
  4361.   LVAL form; int cont;
  4362. {
  4363.     if (atom(form))
  4364.         xlerror("expecting symbol or function template",form);
  4365.     define1(car(form),cdr(form),cont);
  4366. }
  4367.  
  4368. /* define1 - helper routine for do_define */
  4369. LOCAL define1(list,body,cont)
  4370.   LVAL list,body; int cont;
  4371. {
  4372.     LVAL fargs;
  4373.     int off;
  4374.  
  4375.     /* handle nested definitions */
  4376.     if (consp(list)) {
  4377.         cpush(cons(xlenter("LAMBDA"),NIL));     /* (LAMBDA) */
  4378.         rplacd(top(),cons(cdr(list),NIL));      /* (LAMBDA args) */
  4379.         rplacd(cdr(top()),body);                /* (LAMBDA args body) */
  4380.         settop(cons(top(),NIL));                /* ((LAMBDA args body)) */
  4381.         define1(car(list),top(),cont);
  4382.         drop(1);
  4383.     }
  4384.     
  4385.     /* compile procedure definitions */
  4386.     else {
  4387.  
  4388.         /* make sure it's a symbol */
  4389.         if (!symbolp(list))
  4390.             xlerror("expecting a symbol",list);
  4391.  
  4392.         /* check for a procedure definition */
  4393.         if (consp(body)
  4394.         &&  consp(car(body))
  4395.         &&  car(car(body)) == xlenter("LAMBDA")) {
  4396.             fargs = car(cdr(car(body)));
  4397.             body = cdr(cdr(car(body)));
  4398.             cd_fundefinition(list,fargs,body);
  4399.         }
  4400.  
  4401.         /* compile the value expression or procedure body */
  4402.         else
  4403.             do_begin(body,C_NEXT);
  4404.     
  4405.         /* define the variable value */
  4406.         if (findcvariable(list,&off))
  4407.             cd_evariable(OP_ESET,0,off);
  4408.         else
  4409.             cd_variable(OP_GSET,list);
  4410.         do_literal(list,cont);
  4411.     }
  4412. }
  4413.  
  4414. /* do_set - compile the (SET! ... ) expression */
  4415. LOCAL do_set(form,cont)
  4416.   LVAL form; int cont;
  4417. {
  4418.     if (atom(form))
  4419.         xlerror("expecting symbol or ACCESS form",form);
  4420.     else if (symbolp(car(form)))
  4421.         do_setvar(form,cont);
  4422.     else if (consp(car(form)))
  4423.         do_setaccess(form,cont);
  4424.     else
  4425.         xlerror("expecting symbol or ACCESS form",form);
  4426. }
  4427.  
  4428. /* do_setvar - compile the (SET! var value) expression */
  4429. LOCAL do_setvar(form,cont)
  4430.   LVAL form; int cont;
  4431. {
  4432.     int lev,off;
  4433.     LVAL sym;
  4434.  
  4435.     /* get the variable name */
  4436.     sym = car(form);
  4437.  
  4438.     /* compile the value expression */
  4439.     form = cdr(form);
  4440.     if (atom(form))
  4441.         xlerror("expecting value expression",form);
  4442.     do_expr(car(form),C_NEXT);
  4443.  
  4444.     /* set the variable value */
  4445.     if (findvariable(sym,&lev,&off))
  4446.         cd_evariable(OP_ESET,lev,off);
  4447.     else
  4448.         cd_variable(OP_GSET,sym);
  4449.     do_continuation(cont);
  4450. }
  4451.  
  4452. /* do_quote - compile the (QUOTE ... ) expression */
  4453. LOCAL do_quote(form,cont)
  4454.   LVAL form; int cont;
  4455. {
  4456.     if (atom(form))
  4457.         xlerror("expecting quoted expression",form);
  4458.     do_literal(car(form),cont);
  4459. }
  4460.  
  4461. /* do_lambda - compile the (LAMBDA ... ) expression */
  4462. LOCAL do_lambda(form,cont)
  4463.   LVAL form; int cont;
  4464. {
  4465.     if (atom(form))
  4466.         xlerror("expecting argument list",form);
  4467.     cd_fundefinition(NIL,car(form),cdr(form));
  4468.     do_continuation(cont);
  4469. }
  4470.  
  4471. /* cd_fundefinition - compile the function */
  4472. LOCAL cd_fundefinition(fun,fargs,body)
  4473.   LVAL fun,fargs,body;
  4474. {
  4475.     int oldcbase;
  4476.  
  4477.     /* establish a new environment frame */
  4478.     oldcbase = add_level();
  4479.  
  4480.     /* compile the lambda list and the function body */
  4481.     parse_lambda_list(fargs,body);
  4482.     do_begin(body,C_RETURN);
  4483.  
  4484.     /* build the code object */
  4485.     cpush(make_code_object(fun));
  4486.     
  4487.     /* restore the previous environment */
  4488.     remove_level(oldcbase);
  4489.  
  4490.     /* compile code to create a closure */
  4491.     do_literal(pop(),C_NEXT);
  4492.     putcbyte(OP_CLOSE);
  4493. }
  4494.  
  4495. /* parse_lambda_list - parse the formal argument list */
  4496. LOCAL parse_lambda_list(fargs,body)
  4497.   LVAL fargs,body;
  4498. {
  4499.     LVAL arg,restarg,new,last;
  4500.     int frame,slotn;
  4501.     
  4502.     /* setup the entry code */
  4503.     putcbyte(OP_FRAME);
  4504.     frame = putcbyte(0);
  4505.  
  4506.     /* initialize the argument name list and slot number */
  4507.     restarg = last = NIL;
  4508.     slotn = 1;
  4509.     
  4510.     /* handle each required argument */
  4511.     while (consp(fargs) && (arg = car(fargs)) && !lambdakey(arg)) {
  4512.  
  4513.         /* make sure the argument is a symbol */
  4514.         if (!symbolp(arg))
  4515.             xlerror("variable must be a symbol",arg);
  4516.  
  4517.         /* add the argument name to the name list */
  4518.         new = cons(arg,NIL);
  4519.         if (last) rplacd(last,new);
  4520.         else setelement(car(car(info)),0,new);
  4521.         last = new;
  4522.  
  4523.         /* generate an instruction to move the argument into the frame */
  4524.         putcbyte(OP_MVARG);
  4525.         putcbyte(slotn++);
  4526.         
  4527.         /* move the formal argument list pointer ahead */
  4528.         fargs = cdr(fargs);
  4529.     }
  4530.  
  4531.     /* check for the '#!optional' argument */
  4532.     if (consp(fargs) && car(fargs) == lk_optional) {
  4533.         fargs = cdr(fargs);
  4534.  
  4535.         /* handle each optional argument */
  4536.         while (consp(fargs) && (arg = car(fargs)) && !lambdakey(arg)) {
  4537.  
  4538.             /* make sure the argument is a symbol */
  4539.             if (!symbolp(arg))
  4540.                 xlerror("#!optional variable must be a symbol",arg);
  4541.  
  4542.             /* add the argument name to the name list */
  4543.             new = cons(arg,NIL);
  4544.             if (last) rplacd(last,new);
  4545.             else setelement(car(car(info)),0,new);
  4546.             last = new;
  4547.  
  4548.             /* move the argument into the frame */
  4549.             putcbyte(OP_MVOARG);
  4550.             putcbyte(slotn++);
  4551.         
  4552.             /* move the formal argument list pointer ahead */
  4553.             fargs = cdr(fargs);
  4554.         }
  4555.     }
  4556.  
  4557.     /* check for the '#!rest' argument */
  4558.     if (consp(fargs) && car(fargs) == lk_rest) {
  4559.         fargs = cdr(fargs);
  4560.  
  4561.         /* handle the rest argument */
  4562.         if (consp(fargs) && (restarg = car(fargs)) && !lambdakey(restarg)) {
  4563.  
  4564.             /* make sure the argument is a symbol */
  4565.             if (!symbolp(restarg))
  4566.                 xlerror("#!rest variable must be a symbol",restarg);
  4567.  
  4568.             /* add the argument name to the name list */
  4569.             new = cons(restarg,NIL);
  4570.             if (last) rplacd(last,new);
  4571.             else setelement(car(car(info)),0,new);
  4572.             last = new;
  4573.  
  4574.             /* make the #!rest argument list */
  4575.             putcbyte(OP_MVRARG);
  4576.             putcbyte(slotn++);
  4577.  
  4578.             /* move the formal argument list pointer ahead */
  4579.             fargs = cdr(fargs);
  4580.         }
  4581.         else
  4582.             xlerror("expecting the #!rest variable");
  4583.     }
  4584.  
  4585.     /* check for the a dotted tail */
  4586.     if (restarg == NIL && symbolp(fargs)) {
  4587.         restarg = fargs;
  4588.  
  4589.         /* add the argument name to the name list */
  4590.         new = cons(restarg,NIL);
  4591.         if (last) rplacd(last,new);
  4592.         else setelement(car(car(info)),0,new);
  4593.         last = new;
  4594.  
  4595.         /* make the #!rest argument list */
  4596.         putcbyte(OP_MVRARG);
  4597.         putcbyte(slotn++);
  4598.         fargs = NIL;
  4599.     }
  4600.  
  4601.     /* check for the end of the argument list */
  4602.     if (fargs != NIL)
  4603.         xlerror("bad argument list tail",fargs);
  4604.  
  4605.     /* make sure the user didn't supply too many arguments */
  4606.     if (restarg == NIL)
  4607.         putcbyte(OP_ALAST);
  4608.         
  4609.     /* scan the body for internal definitions */
  4610.     slotn += find_internal_definitions(body,last);
  4611.         
  4612.     /* fixup the frame instruction */
  4613.     cbuff[cbase+frame] = slotn;
  4614. }
  4615.  
  4616. /* find_internal_definitions - find internal definitions */
  4617. LOCAL int find_internal_definitions(body,last)
  4618.   LVAL body,last;
  4619. {
  4620.     LVAL define,sym,new;
  4621.     int n=0;
  4622.  
  4623.     /* look for all (define...) forms */
  4624.     for (define = xlenter("DEFINE"); consp(body); body = cdr(body))
  4625.         if (consp(car(body)) && car(car(body)) == define) {
  4626.             sym = cdr(car(body)); /* the rest of the (define...) form */
  4627.             if (consp(sym)) {     /* make sure there is a second subform */
  4628.                 sym = car(sym);   /* get the second subform */
  4629.                 while (consp(sym))/* check for a procedure definition */
  4630.                     sym = car(sym);
  4631.                 if (symbolp(sym)) {
  4632.                     new = cons(sym,NIL);
  4633.                     if (last) rplacd(last,new);
  4634.                     else setelement(car(car(info)),0,new);
  4635.                     last = new;
  4636.                     ++n;
  4637.                 }
  4638.             }
  4639.         }
  4640.     return (n);
  4641. }
  4642.  
  4643. /* do_delay - compile the (DELAY ... ) expression */
  4644. LOCAL do_delay(form,cont)
  4645.   LVAL form; int cont;
  4646. {
  4647.     int oldcbase;
  4648.  
  4649.     /* check argument list */
  4650.     if (atom(form))
  4651.         xlerror("expecting delay expression",form);
  4652.  
  4653.     /* establish a new environment frame */
  4654.     oldcbase = add_level();
  4655.  
  4656.     /* setup the entry code */
  4657.     putcbyte(OP_FRAME);
  4658.     putcbyte(1);
  4659.  
  4660.     /* compile the expression */
  4661.     do_expr(car(form),C_RETURN);
  4662.  
  4663.     /* build the code object */
  4664.     cpush(make_code_object(NIL));
  4665.     
  4666.     /* restore the previous environment */
  4667.     remove_level(oldcbase);
  4668.  
  4669.     /* compile code to create a closure */
  4670.     do_literal(pop(),C_NEXT);
  4671.     putcbyte(OP_DELAY);
  4672.     do_continuation(cont);
  4673. }
  4674.  
  4675. /* do_let - compile the (LET ... ) expression */
  4676. LOCAL do_let(form,cont)
  4677.   LVAL form; int cont;
  4678. {
  4679.     /* handle named let */
  4680.     if (consp(form) && symbolp(car(form)))
  4681.         do_named_let(form,cont);
  4682.     
  4683.     /* handle unnamed let */
  4684.     else
  4685.         cd_let(NIL,form,cont);
  4686. }
  4687.  
  4688. /* do_named_let - compile the (LET name ... ) expression */
  4689. LOCAL do_named_let(form,cont)
  4690.   LVAL form; int cont;
  4691. {
  4692.     int oldcbase,nxt;
  4693.  
  4694.     /* save a continuation */
  4695.     if (cont != C_RETURN) {
  4696.         putcbyte(OP_SAVE);
  4697.         nxt = putcword(0);
  4698.     }
  4699.     
  4700.     /* establish a new environment frame */
  4701.     oldcbase = add_level();
  4702.     setelement(car(car(info)),0,cons(car(form),NIL));
  4703.  
  4704.     /* setup the entry code */
  4705.     putcbyte(OP_FRAME);
  4706.     putcbyte(2);
  4707.     
  4708.     /* compile the let expression */
  4709.     cd_let(car(form),cdr(form),C_RETURN);
  4710.  
  4711.     /* build the code object */
  4712.     cpush(make_code_object(NIL));
  4713.     
  4714.     /* restore the previous environment */
  4715.     remove_level(oldcbase);
  4716.  
  4717.     /* compile code to create a closure */
  4718.     do_literal(pop(),C_NEXT);
  4719.     putcbyte(OP_CLOSE);
  4720.  
  4721.     /* apply the function */
  4722.     putcbyte(OP_CALL);
  4723.     putcbyte(1);
  4724.  
  4725.     /* target for the continuation */
  4726.     if (cont != C_RETURN)
  4727.         fixup(nxt);
  4728. }
  4729.  
  4730. /* cd_let - code a let expression */
  4731. LOCAL cd_let(name,form,cont)
  4732.   LVAL name,form; int cont;
  4733. {
  4734.     int oldcbase,nxt,lev,off,n;
  4735.  
  4736.     /* make sure there is a binding list */
  4737.     if (atom(form) || !listp(car(form)))
  4738.         xlerror("expecting binding list",form);
  4739.  
  4740.     /* save a continuation */
  4741.     if (cont != C_RETURN) {
  4742.         putcbyte(OP_SAVE);
  4743.         nxt = putcword(0);
  4744.     }
  4745.     
  4746.     /* push the initialization expressions */
  4747.     n = push_init_expressions(car(form));
  4748.  
  4749.     /* establish a new environment frame */
  4750.     oldcbase = add_level();
  4751.  
  4752.     /* compile the binding list */
  4753.     parse_let_variables(car(form),cdr(form));
  4754.  
  4755.     /* compile the body of the let/letrec */
  4756.     do_begin(cdr(form),C_RETURN);
  4757.  
  4758.     /* build the code object */
  4759.     cpush(make_code_object(NIL));
  4760.     
  4761.     /* restore the previous environment */
  4762.     remove_level(oldcbase);
  4763.  
  4764.     /* compile code to create a closure */
  4765.     do_literal(pop(),C_NEXT);
  4766.     putcbyte(OP_CLOSE);
  4767.  
  4768.     /* store the procedure */
  4769.     if (name && findvariable(name,&lev,&off))
  4770.         cd_evariable(OP_ESET,lev,off);
  4771.  
  4772.     /* apply the function */
  4773.     putcbyte(OP_CALL);
  4774.     putcbyte(n);
  4775.  
  4776.     /* target for the continuation */
  4777.     if (cont != C_RETURN)
  4778.         fixup(nxt);
  4779. }
  4780.  
  4781. /* do_letrec - compile the (LETREC ... ) expression */
  4782. LOCAL do_letrec(form,cont)
  4783.   LVAL form; int cont;
  4784. {
  4785.     int oldcbase,nxt,n;
  4786.  
  4787.     /* make sure there is a binding list */
  4788.     if (atom(form) || !listp(car(form)))
  4789.         xlerror("expecting binding list",form);
  4790.  
  4791.     /* save a continuation */
  4792.     if (cont != C_RETURN) {
  4793.         putcbyte(OP_SAVE);
  4794.         nxt = putcword(0);
  4795.     }
  4796.     
  4797.     /* push the initialization expressions */
  4798.     n = push_dummy_values(car(form));
  4799.  
  4800.     /* establish a new environment frame */
  4801.     oldcbase = add_level();
  4802.  
  4803.     /* compile the binding list */
  4804.     parse_let_variables(car(form),cdr(form));
  4805.  
  4806.     /* compile instructions to set the bound variables */
  4807.     set_bound_variables(car(form));
  4808.     
  4809.     /* compile the body of the let/letrec */
  4810.     do_begin(cdr(form),C_RETURN);
  4811.  
  4812.     /* build the code object */
  4813.     cpush(make_code_object(NIL));
  4814.     
  4815.     /* restore the previous environment */
  4816.     remove_level(oldcbase);
  4817.  
  4818.     /* compile code to create a closure */
  4819.     do_literal(pop(),C_NEXT);
  4820.     putcbyte(OP_CLOSE);
  4821.  
  4822.     /* apply the function */
  4823.     putcbyte(OP_CALL);
  4824.     putcbyte(n);
  4825.  
  4826.     /* target for the continuation */
  4827.     if (cont != C_RETURN)
  4828.         fixup(nxt);
  4829. }
  4830.  
  4831. /* do_letstar - compile the (LET* ... ) expression */
  4832. LOCAL do_letstar(form,cont)
  4833.   LVAL form; int cont;
  4834. {
  4835.     int nxt;
  4836.     
  4837.     /* make sure there is a binding list */
  4838.     if (atom(form) || !listp(car(form)))
  4839.         xlerror("expecting binding list",form);
  4840.  
  4841.     /* handle the case where there are bindings */
  4842.     if (consp(car(form))) {
  4843.     
  4844.         /* save a continuation */
  4845.         if (cont != C_RETURN) {
  4846.             putcbyte(OP_SAVE);
  4847.             nxt = putcword(0);
  4848.         }
  4849.     
  4850.         /* build the nested lambda expressions */
  4851.         letstar1(car(form),cdr(form));
  4852.     
  4853.         /* target for the continuation */
  4854.         if (cont != C_RETURN)
  4855.             fixup(nxt);
  4856.     }
  4857.     
  4858.     /* handle the case where there are no bindings */
  4859.     else
  4860.         do_begin(cdr(form),cont);
  4861. }
  4862.  
  4863. /* letstar1 - helper routine for let* */
  4864. LOCAL letstar1(blist,body)
  4865.   LVAL blist,body;
  4866. {
  4867.     int oldcbase,n;
  4868.  
  4869.     /* push the next initialization expressions */
  4870.     cpush(cons(car(blist),NIL));
  4871.     n = push_init_expressions(top());
  4872.  
  4873.     /* establish a new environment frame */
  4874.     oldcbase = add_level();
  4875.  
  4876.     /* handle the case where there are more bindings */
  4877.     if (consp(cdr(blist))) {
  4878.         parse_let_variables(top(),NIL);
  4879.         letstar1(cdr(blist),body);
  4880.     }
  4881.     
  4882.     /* handle the last binding */
  4883.     else {
  4884.         parse_let_variables(top(),body);
  4885.         do_begin(body,C_RETURN);
  4886.     }
  4887.         
  4888.     /* build the code object */
  4889.     settop(make_code_object(NIL));
  4890.     
  4891.     /* restore the previous environment */
  4892.     remove_level(oldcbase);
  4893.  
  4894.     /* compile code to create a closure */
  4895.     do_literal(pop(),C_NEXT);
  4896.     putcbyte(OP_CLOSE);
  4897.  
  4898.     /* apply the function */
  4899.     putcbyte(OP_CALL);
  4900.     putcbyte(n);
  4901. }
  4902.  
  4903. /* push_dummy_values - push dummy values for a 'letrec' expression */
  4904. LOCAL int push_dummy_values(blist)
  4905.   LVAL blist;
  4906. {
  4907.     int n=0;
  4908.     if (consp(blist)) {
  4909.         putcbyte(OP_NIL);
  4910.         for (; consp(blist); blist = cdr(blist), ++n)
  4911.             putcbyte(OP_PUSH);
  4912.     }
  4913.     return (n);
  4914. }
  4915.  
  4916. /* push_init_expressions - push init expressions for a 'let' expression */
  4917. LOCAL int push_init_expressions(blist)
  4918.   LVAL blist;
  4919. {
  4920.     int n;
  4921.     if (consp(blist)) {
  4922.         n = push_init_expressions(cdr(blist));
  4923.         if (consp(car(blist)) && consp(cdr(car(blist))))
  4924.             do_expr(car(cdr(car(blist))),C_NEXT);
  4925.         else
  4926.             putcbyte(OP_NIL);
  4927.         putcbyte(OP_PUSH);
  4928.         return (n+1);
  4929.     }
  4930.     return (0);
  4931. }
  4932.  
  4933. /* parse_let_variables - parse the binding list */
  4934. LOCAL parse_let_variables(blist,body)
  4935.   LVAL blist,body;
  4936. {
  4937.     LVAL arg,new,last;
  4938.     int frame,slotn;
  4939.     
  4940.     /* setup the entry code */
  4941.     putcbyte(OP_FRAME);
  4942.     frame = putcbyte(0);
  4943.  
  4944.     /* initialize the argument name list and slot number */
  4945.     last = NIL;
  4946.     slotn = 1;
  4947.     
  4948.     /* handle each required argument */
  4949.     while (consp(blist) && (arg = car(blist))) {
  4950.  
  4951.         /* make sure the argument is a symbol */
  4952.         if (symbolp(arg))
  4953.             new = cons(arg,NIL);
  4954.         else if (consp(arg) && symbolp(car(arg)))
  4955.             new = cons(car(arg),NIL);
  4956.         else
  4957.             xlerror("invalid binding",arg);
  4958.  
  4959.         /* add the argument name to the name list */
  4960.         if (last) rplacd(last,new);
  4961.         else setelement(car(car(info)),0,new);
  4962.         last = new;
  4963.  
  4964.         /* generate an instruction to move the argument into the frame */
  4965.         putcbyte(OP_MVARG);
  4966.         putcbyte(slotn++);
  4967.         
  4968.         /* move the formal argument list pointer ahead */
  4969.         blist = cdr(blist);
  4970.     }
  4971.     putcbyte(OP_ALAST);
  4972.  
  4973.     /* scan the body for internal definitions */
  4974.     slotn += find_internal_definitions(body,last);
  4975.         
  4976.     /* fixup the frame instruction */
  4977.     cbuff[cbase+frame] = slotn;
  4978. }
  4979.  
  4980. /* set_bound_variables - set bound variables in a 'letrec' expression */
  4981. LOCAL set_bound_variables(blist)
  4982.   LVAL blist;
  4983. {
  4984.     int lev,off;
  4985.     for (; consp(blist); blist = cdr(blist)) {
  4986.         if (consp(car(blist)) && consp(cdr(car(blist)))) {
  4987.             do_expr(car(cdr(car(blist))),C_NEXT);
  4988.             if (findvariable(car(car(blist)),&lev,&off))
  4989.                 cd_evariable(OP_ESET,lev,off);
  4990.             else
  4991.                 xlerror("compiler error -- can't find",car(car(blist)));
  4992.         }
  4993.     }
  4994. }
  4995.  
  4996. /* make_code_object - build a code object */
  4997. LOCAL LVAL make_code_object(fun)
  4998.   LVAL fun;
  4999. {
  5000.     unsigned char *cp;
  5001.     LVAL code,p;
  5002.     int i;
  5003.  
  5004.     /* create a code object */
  5005.     code = newcode(FIRSTLIT + length(car(cdr(info)))); cpush(code);
  5006.     setbcode(code,newstring(cptr - cbase));
  5007.     setcname(code,fun);                          /* function name */
  5008.     setvnames(code,getelement(car(car(info)),0));/* lambda list variables */
  5009.  
  5010.     /* copy the literals into the code object */
  5011.     for (i = FIRSTLIT, p = car(cdr(info)); consp(p); p = cdr(p), ++i)
  5012.         setelement(code,i,car(p));
  5013.  
  5014.     /* copy the byte codes */
  5015.     for (i = cbase, cp = getstring(getbcode(code)); i < cptr; )
  5016.         *cp++ = cbuff[i++];
  5017.  
  5018.     /* return the new code object */
  5019.     return (pop());
  5020. }
  5021.  
  5022. /* do_cond - compile the (COND ... ) expression */
  5023. LOCAL do_cond(form,cont)
  5024.   LVAL form; int cont;
  5025. {
  5026.     int nxt,end;
  5027.     if (consp(form)) {
  5028.         for (end = 0; consp(form); form = cdr(form)) {
  5029.             if (atom(car(form)))
  5030.                 xlerror("expecting a cond clause",form);
  5031.             do_expr(car(car(form)),C_NEXT);
  5032.             putcbyte(OP_BRF);
  5033.             nxt = putcword(0);
  5034.             if (cdr(car(form)))
  5035.                 do_begin(cdr(car(form)),cont);
  5036.             else
  5037.                 do_continuation(cont);
  5038.             if (cont == C_NEXT) {
  5039.                 putcbyte(OP_BR);
  5040.                 end = putcword(end);
  5041.             }
  5042.             fixup(nxt);
  5043.         }
  5044.         fixup(end);
  5045.     }
  5046.     else
  5047.         putcbyte(OP_NIL);
  5048.     do_continuation(cont);
  5049. }
  5050.  
  5051. /* do_and - compile the (AND ... ) expression */
  5052. LOCAL do_and(form,cont)
  5053.   LVAL form; int cont;
  5054. {
  5055.     int end;
  5056.     if (consp(form)) {
  5057.         for (end = 0; consp(form); form = cdr(form)) {
  5058.             if (cdr(form)) {
  5059.                 do_expr(car(form),C_NEXT);
  5060.                 putcbyte(OP_BRF);
  5061.                 end = putcword(end);
  5062.             }
  5063.             else
  5064.                 do_expr(car(form),cont);
  5065.         }
  5066.         fixup(end);
  5067.     }
  5068.     else
  5069.         putcbyte(OP_T);
  5070.     do_continuation(cont);
  5071. }
  5072.  
  5073. /* do_or - compile the (OR ... ) expression */
  5074. LOCAL do_or(form,cont)
  5075.   LVAL form; int cont;
  5076. {
  5077.     int end;
  5078.     if (consp(form)) {
  5079.         for (end = 0; consp(form); form = cdr(form)) {
  5080.             if (cdr(form)) {
  5081.                 do_expr(car(form),C_NEXT);
  5082.                 putcbyte(OP_BRT);
  5083.                 end = putcword(end);
  5084.             }
  5085.             else
  5086.                 do_expr(car(form),cont);
  5087.         }
  5088.         fixup(end);
  5089.     }
  5090.     else
  5091.         putcbyte(OP_NIL);
  5092.     do_continuation(cont);
  5093. }
  5094.  
  5095. /* do_if - compile the (IF ... ) expression */
  5096. LOCAL do_if(form,cont)
  5097.   LVAL form; int cont;
  5098. {
  5099.     int nxt,end;
  5100.  
  5101.     /* compile the test expression */
  5102.     if (atom(form))
  5103.         xlerror("expecting test expression",form);
  5104.     do_expr(car(form),C_NEXT);
  5105.  
  5106.     /* skip around the 'then' clause if the expression is false */
  5107.     putcbyte(OP_BRF);
  5108.     nxt = putcword(0);
  5109.  
  5110.     /* skip to the 'then' clause */
  5111.     form = cdr(form);
  5112.     if (atom(form))
  5113.         xlerror("expecting then clause",form);
  5114.  
  5115.     /* compile the 'then' and 'else' clauses */
  5116.     if (consp(cdr(form))) {
  5117.         if (cont == C_NEXT) {
  5118.             do_expr(car(form),C_NEXT);
  5119.             putcbyte(OP_BR);
  5120.             end = putcword(0);
  5121.         }
  5122.         else {
  5123.             do_expr(car(form),cont);
  5124.             end = -1;
  5125.         }
  5126.         fixup(nxt);
  5127.         do_expr(car(cdr(form)),cont);
  5128.         nxt = end;
  5129.     }
  5130.  
  5131.     /* compile just a 'then' clause */
  5132.     else
  5133.         do_expr(car(form),cont);
  5134.  
  5135.     /* handle the end of the statement */
  5136.     if (nxt >= 0) {
  5137.         fixup(nxt);
  5138.         do_continuation(cont);
  5139.     }
  5140. }
  5141.  
  5142. /* do_begin - compile the (BEGIN ... ) expression */
  5143. LOCAL do_begin(form,cont)
  5144.   LVAL form; int cont;
  5145. {
  5146.     if (consp(form))
  5147.         for (; consp(form); form = cdr(form))
  5148.             if (consp(cdr(form)))
  5149.                 do_expr(car(form),C_NEXT);
  5150.             else
  5151.                 do_expr(car(form),cont);
  5152.     else {
  5153.         putcbyte(OP_NIL);
  5154.         do_continuation(cont);
  5155.     }
  5156. }
  5157.  
  5158. /* do_while - compile the (WHILE ... ) expression */
  5159. LOCAL do_while(form,cont)
  5160.   LVAL form; int cont;
  5161. {
  5162.     int loop,nxt;
  5163.  
  5164.     /* make sure there is a test expression */
  5165.     if (atom(form))
  5166.         xlerror("expecting test expression",form);
  5167.  
  5168.     /* skip around the 'body' to the test expression */
  5169.     putcbyte(OP_BR);
  5170.     nxt = putcword(0);
  5171.  
  5172.     /* compile the loop body */
  5173.     loop = cptr - cbase;
  5174.     do_begin(cdr(form),C_NEXT);
  5175.  
  5176.     /* label for the first iteration */
  5177.     fixup(nxt);
  5178.  
  5179.     /* compile the test expression */
  5180.     nxt = cptr - cbase;
  5181.     do_expr(car(form),C_NEXT);
  5182.  
  5183.     /* skip around the 'body' if the expression is false */
  5184.     putcbyte(OP_BRT);
  5185.     putcword(loop);
  5186.  
  5187.     /* compile the continuation */
  5188.     do_continuation(cont);
  5189. }
  5190.  
  5191. /* do_access - compile the (ACCESS var env) expression */
  5192. LOCAL do_access(form,cont)
  5193.   LVAL form; int cont;
  5194. {
  5195.     LVAL sym;
  5196.  
  5197.     /* get the variable name */
  5198.     if (atom(form) || !symbolp(car(form)))
  5199.         xlerror("expecting symbol",form);
  5200.     sym = car(form);
  5201.  
  5202.     /* compile the environment expression */
  5203.     form = cdr(form);
  5204.     if (atom(form))
  5205.         xlerror("expecting environment expression",form);
  5206.     do_expr(car(form),C_NEXT);
  5207.  
  5208.     /* get the variable value */
  5209.     cd_variable(OP_AREF,sym);
  5210.     do_continuation(cont);
  5211. }
  5212.  
  5213. /* do_setaccess - compile the (SET! (ACCESS var env) value) expression */
  5214. LOCAL do_setaccess(form,cont)
  5215.   LVAL form; int cont;
  5216. {
  5217.     LVAL aform,sym;
  5218.  
  5219.     /* make sure this is an access form */
  5220.     aform = car(form);
  5221.     if (atom(aform) || car(aform) != xlenter("ACCESS"))
  5222.         xlerror("expecting an ACCESS form",aform);
  5223.  
  5224.     /* get the variable name */
  5225.     aform = cdr(aform);
  5226.     if (atom(aform) || !symbolp(car(aform)))
  5227.         xlerror("expecting symbol",aform);
  5228.     sym = car(aform);
  5229.  
  5230.     /* compile the environment expression */
  5231.     aform = cdr(aform);
  5232.     if (atom(aform))
  5233.         xlerror("expecting environment expression",aform);
  5234.     do_expr(car(aform),C_NEXT);
  5235.     putcbyte(OP_PUSH);
  5236.  
  5237.     /* compile the value expression */
  5238.     form = cdr(form);
  5239.     if (atom(form))
  5240.         xlerror("expecting value expression",form);
  5241.     do_expr(car(form),C_NEXT);
  5242.  
  5243.     /* set the variable value */
  5244.     cd_variable(OP_ASET,sym);
  5245.     do_continuation(cont);
  5246. }
  5247.  
  5248. /* do_call - compile a function call */
  5249. LOCAL do_call(form,cont)
  5250.   LVAL form; int cont;
  5251. {
  5252.     int nxt,n;
  5253.     
  5254.     /* save a continuation */
  5255.     if (cont != C_RETURN) {
  5256.         putcbyte(OP_SAVE);
  5257.         nxt = putcword(0);
  5258.     }
  5259.     
  5260.     /* compile each argument expression */
  5261.     n = push_args(cdr(form));
  5262.  
  5263.     /* compile the function itself */
  5264.     do_expr(car(form),C_NEXT);
  5265.  
  5266.     /* apply the function */
  5267.     putcbyte(OP_CALL);
  5268.     putcbyte(n);
  5269.  
  5270.     /* target for the continuation */
  5271.     if (cont != C_RETURN)
  5272.         fixup(nxt);
  5273. }
  5274.  
  5275. /* push_args - compile the arguments for a function call */
  5276. LOCAL int push_args(form)
  5277.   LVAL form;
  5278. {
  5279.     int n;
  5280.     if (consp(form)) {
  5281.         n = push_args(cdr(form));
  5282.         do_expr(car(form),C_NEXT);
  5283.         putcbyte(OP_PUSH);
  5284.         return (n+1);
  5285.     }
  5286.     return (0);
  5287. }
  5288.  
  5289. /* do_nary - compile nary operator expressions */
  5290. LOCAL do_nary(op,n,form,cont)
  5291.   int op,n; LVAL form; int cont;
  5292. {
  5293.     if (n < 0 && (n = (-n)) != length(cdr(form)))
  5294.         do_call(form,cont);
  5295.     else {
  5296.         push_nargs(cdr(form),n);
  5297.         putcbyte(op);
  5298.         do_continuation(cont);
  5299.     }
  5300. }
  5301.  
  5302. /* push_nargs - compile the arguments for an inline function call */
  5303. LOCAL int push_nargs(form,n)
  5304.   LVAL form; int n;
  5305. {
  5306.     if (consp(form)) {
  5307.         if (n == 0)
  5308.             xlerror("too many arguments",form);
  5309.         if (push_nargs(cdr(form),n-1))
  5310.             putcbyte(OP_PUSH);
  5311.         do_expr(car(form),C_NEXT);
  5312.         return (TRUE);
  5313.     }
  5314.     if (n)
  5315.         xlerror("too few arguments",form);
  5316.     return (FALSE);
  5317. }
  5318.  
  5319. /* do_literal - compile a literal */
  5320. LOCAL do_literal(lit,cont)
  5321.   LVAL lit; int cont;
  5322. {
  5323.     cd_literal(lit);
  5324.     do_continuation(cont);
  5325. }
  5326.  
  5327. /* do_identifier - compile an identifier */
  5328. LOCAL do_identifier(sym,cont)
  5329.   LVAL sym; int cont;
  5330. {
  5331.     int lev,off;
  5332.     if (sym == true_lval)
  5333.         putcbyte(OP_T);
  5334.     else if (findvariable(sym,&lev,&off))
  5335.         cd_evariable(OP_EREF,lev,off);
  5336.     else
  5337.         cd_variable(OP_GREF,sym);
  5338.     do_continuation(cont);
  5339. }
  5340.  
  5341. /* do_continuation - compile a continuation */
  5342. LOCAL do_continuation(cont)
  5343.   int cont;
  5344. {
  5345.     switch (cont) {
  5346.     case C_RETURN:
  5347.         putcbyte(OP_RETURN);
  5348.         break;
  5349.     case C_NEXT:
  5350.         break;
  5351.     }
  5352. }
  5353.  
  5354. /* add_level - add a nesting level */
  5355. LOCAL int add_level()
  5356. {
  5357.     int oldcbase;
  5358.     
  5359.     /* establish a new environment frame */
  5360.     rplaca(info,newframe(car(info),1));
  5361.     rplacd(info,cons(NIL,cdr(info)));
  5362.  
  5363.     /* setup the base of the code for this function */
  5364.     oldcbase = cbase;
  5365.     cbase = cptr;
  5366.  
  5367.     /* return the old code base */
  5368.     return (oldcbase);
  5369. }
  5370.  
  5371. /* remove_level - remove a nesting level */
  5372. LOCAL remove_level(oldcbase)
  5373.   int oldcbase;
  5374. {
  5375.     /* restore the previous environment */
  5376.     rplaca(info,cdr(car(info)));
  5377.     rplacd(info,cdr(cdr(info)));
  5378.  
  5379.     /* restore the base and code pointer */
  5380.     cptr = cbase;
  5381.     cbase = oldcbase;
  5382. }
  5383.  
  5384. /* findvariable - find an environment variable */
  5385. LOCAL int findvariable(sym,plev,poff)
  5386.   LVAL sym; int *plev,*poff;
  5387. {
  5388.     int lev,off;
  5389.     LVAL e,a;
  5390.     for (e = car(info), lev = 0; envp(e); e = cdr(e), ++lev)
  5391.         for (a = getelement(car(e),0), off = 1; consp(a); a = cdr(a), ++off)
  5392.             if (sym == car(a)) {
  5393.                 *plev = lev;
  5394.                 *poff = off;
  5395.                 return (TRUE);
  5396.             }
  5397.     return (FALSE);
  5398. }
  5399.  
  5400. /* findcvariable - find an environment variable in the current frame */
  5401. LOCAL int findcvariable(sym,poff)
  5402.   LVAL sym; int *poff;
  5403. {
  5404.     int off;
  5405.     LVAL a;
  5406.     a = getelement(car(car(info)),0);
  5407.     for (off = 1; consp(a); a = cdr(a), ++off)
  5408.         if (sym == car(a)) {
  5409.             *poff = off;
  5410.             return (TRUE);
  5411.         }
  5412.     return (FALSE);
  5413. }
  5414.  
  5415. /* findliteral - find a literal in the literal frame */
  5416. LOCAL int findliteral(lit)
  5417.   LVAL lit;
  5418. {
  5419.     int o = FIRSTLIT;
  5420.     LVAL t,p;
  5421.     if (t = car(cdr(info))) {
  5422.         for (p = NIL; consp(t); p = t, t = cdr(t), ++o)
  5423.             if (equal(lit,car(t)))
  5424.                 return (o);
  5425.         rplacd(p,cons(lit,NIL));
  5426.     }
  5427.     else
  5428.         rplaca(cdr(info),cons(lit,NIL));
  5429.     return (o);
  5430. }
  5431.  
  5432. /* cd_variable - compile a variable reference */
  5433. LOCAL cd_variable(op,sym)
  5434.   int op; LVAL sym;
  5435. {
  5436.     putcbyte(op);
  5437.     putcbyte(findliteral(sym));
  5438. }
  5439.  
  5440. /* cd_evariable - compile an environment variable reference */
  5441. LOCAL cd_evariable(op,lev,off)
  5442.   int op,lev,off;      
  5443. {
  5444.     putcbyte(op);
  5445.     putcbyte(lev);
  5446.     putcbyte(off);
  5447. }
  5448.  
  5449. /* cd_literal - compile a literal reference */
  5450. LOCAL cd_literal(lit)
  5451.   LVAL lit;
  5452. {
  5453.     if (lit == NIL)
  5454.         putcbyte(OP_NIL);
  5455.     else if (lit == true_lval)
  5456.         putcbyte(OP_T);
  5457.     else {
  5458.         putcbyte(OP_LIT);
  5459.         putcbyte(findliteral(lit));
  5460.     }
  5461. }
  5462.  
  5463. /* putcbyte - put a code byte into data space */
  5464. LOCAL int putcbyte(b)
  5465.   int b;
  5466. {
  5467.     int adr;
  5468.     if (cptr >= CMAX)
  5469.         xlabort("insufficient code space");
  5470.     adr = (cptr - cbase);
  5471.     cbuff[cptr++] = b;
  5472.     return (adr);
  5473. }
  5474.  
  5475. /* putcword - put a code word into data space */
  5476. LOCAL int putcword(w)
  5477.   int w;
  5478. {
  5479.     int adr;
  5480.     adr = putcbyte(w >> 8);
  5481.     putcbyte(w);
  5482.     return (adr);
  5483. }
  5484.  
  5485. /* fixup - fixup a reference chain */
  5486. LOCAL fixup(chn)
  5487.   int chn;
  5488. {
  5489.     int val,hval,nxt;
  5490.  
  5491.     /* store the value into each location in the chain */
  5492.     val = cptr - cbase; hval = val >> 8;
  5493.     for (; chn; chn = nxt) {
  5494.         nxt = (cbuff[cbase+chn] << 8) | (cbuff[cbase+chn+1]);
  5495.         cbuff[cbase+chn] = hval;
  5496.         cbuff[cbase+chn+1] = val;
  5497.     }
  5498. }
  5499.  
  5500. /* length - find the length of a list */
  5501. int length(list)
  5502.   LVAL list;
  5503. {
  5504.     int len;
  5505.     for (len = 0; consp(list); list = cdr(list))
  5506.         ++len;
  5507.     return (len);
  5508. }
  5509.  
  5510. /* instruction output formats */
  5511. #define FMT_NONE        0
  5512. #define FMT_BYTE        1
  5513. #define FMT_LOFF        2
  5514. #define FMT_WORD        3
  5515. #define FMT_EOFF        4
  5516.  
  5517. typedef struct { int ot_code; char *ot_name; int ot_fmt; } OTDEF;
  5518. OTDEF otab[] = {
  5519. {       OP_BRT,         "BRT",          FMT_WORD        },
  5520. {       OP_BRF,         "BRF",          FMT_WORD        },
  5521. {       OP_BR,          "BR",           FMT_WORD        },
  5522. {       OP_LIT,         "LIT",          FMT_LOFF        },
  5523. {       OP_GREF,        "GREF",         FMT_LOFF        },
  5524. {       OP_GSET,        "GSET",         FMT_LOFF        },
  5525. {       OP_EREF,        "EREF",         FMT_EOFF        },
  5526. {       OP_ESET,        "ESET",         FMT_EOFF        },
  5527. {       OP_SAVE,        "SAVE",         FMT_WORD        },
  5528. {       OP_CALL,        "CALL",         FMT_BYTE        },
  5529. {       OP_RETURN,      "RETURN",       FMT_NONE        },
  5530. {       OP_T,           "T",            FMT_NONE        },
  5531. {       OP_NIL,         "NIL",          FMT_NONE        },
  5532. {       OP_PUSH,        "PUSH",         FMT_NONE        },
  5533. {       OP_CLOSE,       "CLOSE",        FMT_NONE        },
  5534. {       OP_DELAY,       "DELAY",        FMT_NONE        },
  5535.  
  5536. {       OP_FRAME,       "FRAME",        FMT_BYTE        },
  5537. {       OP_MVARG,       "MVARG",        FMT_BYTE        },
  5538. {       OP_MVOARG,      "MVOARG",       FMT_BYTE        },
  5539. {       OP_MVRARG,      "MVRARG",       FMT_BYTE        },
  5540. {       OP_ADROP,       "ADROP",        FMT_NONE        },
  5541. {       OP_ALAST,       "ALAST",        FMT_NONE        },
  5542.  
  5543. {       OP_AREF,        "AREF",         FMT_LOFF        },
  5544. {       OP_ASET,        "ASET",         FMT_LOFF        },
  5545.  
  5546. {0,0,0}
  5547. };
  5548.  
  5549. /* decode_procedure - decode the instructions in a code object */
  5550. decode_procedure(fptr,fun)
  5551.   LVAL fptr,fun;
  5552. {
  5553.     int len,lc,n;
  5554.     LVAL code,env;
  5555.     code = getcode(fun);
  5556.     env = getenv(fun);
  5557.     len = getslength(getbcode(code));
  5558.     for (lc = 0; lc < len; lc += n)
  5559.         n = decode_instruction(fptr,code,lc,env);
  5560. }
  5561.  
  5562. /* decode_instruction - decode a single bytecode instruction */
  5563. int decode_instruction(fptr,code,lc,env)
  5564.   LVAL fptr,code; int lc; LVAL env;
  5565. {
  5566.     unsigned char *cp;
  5567.     char buf[100];
  5568.     OTDEF *op;
  5569.     NTDEF *np;
  5570.     int i,n=1;
  5571.     LVAL tmp;
  5572.  
  5573.     /* get a pointer to the bytecodes for this instruction */
  5574.     cp = getstring(getbcode(code)) + lc;
  5575.  
  5576.     /* show the address and opcode */
  5577.     if (tmp = getcname(code))
  5578.         sprintf(buf,"%s:%04x %02x ",getstring(getpname(tmp)),lc,*cp);
  5579.     else {
  5580.         sprintf(buf,AFMT,code); xlputstr(fptr,buf);
  5581.         sprintf(buf,":%04x %02x ",lc,*cp);
  5582.     }
  5583.     xlputstr(fptr,buf);
  5584.  
  5585.     /* display the operands */
  5586.     for (op = otab; op->ot_name; ++op)
  5587.         if (*cp == op->ot_code) {
  5588.             switch (op->ot_fmt) {
  5589.             case FMT_NONE:
  5590.                 sprintf(buf,"      %s\n",op->ot_name);
  5591.                 xlputstr(fptr,buf);
  5592.                 break;
  5593.             case FMT_BYTE:
  5594.                 sprintf(buf,"%02x    %s %02x\n",cp[1],op->ot_name,cp[1]);
  5595.                 xlputstr(fptr,buf);
  5596.                 n += 1;
  5597.                 break;
  5598.             case FMT_LOFF:
  5599.                 sprintf(buf,"%02x    %s %02x ; ",cp[1],op->ot_name,cp[1]);
  5600.                 xlputstr(fptr,buf);
  5601.                 xlprin1(getelement(code,cp[1]),fptr);
  5602.                 xlterpri(fptr);
  5603.                 n += 1;
  5604.                 break;
  5605.             case FMT_WORD:
  5606.                 sprintf(buf,"%02x %02x %s %02x%02x\n",cp[1],cp[2],
  5607.                         op->ot_name,cp[1],cp[2]);
  5608.                 xlputstr(fptr,buf);
  5609.                 n += 2;
  5610.                 break;
  5611.             case FMT_EOFF:
  5612.                 if ((i = cp[1]) == 0)
  5613.                     tmp = getvnames(code);
  5614.                 else {
  5615.                     for (tmp = env; i > 1; --i) tmp = cdr(tmp);
  5616.                     tmp = getelement(car(tmp),0);
  5617.                 }
  5618.                 for (i = cp[2]; i > 1; --i) tmp = cdr(tmp);
  5619.                 sprintf(buf,"%02x %02x %s %02x %02x ; ",cp[1],cp[2],
  5620.                         op->ot_name,cp[1],cp[2]);
  5621.                 xlputstr(fptr,buf);
  5622.                 xlprin1(car(tmp),fptr);
  5623.                 xlterpri(fptr);
  5624.                 n += 2;
  5625.                 break;
  5626.             }
  5627.             return (n);
  5628.         }
  5629.     
  5630.     /* check for an integrable function */
  5631.     for (np = ntab; np->nt_name; ++np)
  5632.         if (*cp == np->nt_code) {
  5633.             sprintf(buf,"      %s\n",np->nt_name);
  5634.             xlputstr(fptr,buf);
  5635.             return (n);
  5636.         }
  5637.  
  5638.     /* unknown opcode */
  5639.     sprintf(buf,"      <UNKNOWN>\n");
  5640.     xlputstr(fptr,buf);
  5641.     return (n);
  5642. }
  5643. (tmp);
  5644.                 sprintf(buf,"%02x %02x %s %02x %02x ; ",cp[1],cp[2],
  5645.                         op->ot_name,cp[1],cp[2]);
  5646.                 xlputstr(fptr,buf);
  5647.                 xlprin1(car(tmp),fptr);
  5648.                 xlterpri(fptr);
  5649.                 n += 2;
  5650.                 break;
  5651.             }
  5652.             return (n);
  5653.         }
  5654.     
  5655.     /* check for an integrable function */
  5656.     for (np = ntab; np->nt_name; ++np)
  5657.         if (*cp == np->nt_code) {
  5658.             sprintf(bsrc/xsdmem.c
  5659. 27   6357
  5660.  
  5661.  
  5662. /*      Copyright (c) 1988, by David Michael Betz
  5663.         All Rights Reserved
  5664.         Permission is granted for unrestricted non-commercial use       */
  5665.  
  5666. #include "xscheme.h"
  5667.  
  5668. /* virtual machine registers */
  5669. LVAL xlfun=NIL;         /* current function */
  5670. LVAL xlenv=NIL;         /* current environment */
  5671. LVAL xlval=NIL;         /* value of most recent instruction */
  5672. LVAL *xlsp=NULL;        /* value stack pointer */
  5673.  
  5674. /* stack limits */
  5675. LVAL *xlstkbase=NULL;   /* base of value stack */
  5676. LVAL *xlstktop=NULL;    /* top of value stack (actually, one beyond) */
  5677.  
  5678. /* variables shared with xsimage.c */
  5679. FIXTYPE total=0;        /* total number of bytes of memory in use */
  5680. FIXTYPE gccalls=0;      /* number of calls to the garbage collector */
  5681.  
  5682. /* node space */
  5683. NSEGMENT *nsegments=NULL;       /* list of node segments */
  5684. NSEGMENT *nslast=NULL;          /* last node segment */
  5685. int nscount=0;                  /* number of node segments */
  5686. FIXTYPE nnodes=0;               /* total number of nodes */
  5687. FIXTYPE nfree=0;                /* number of nodes in free list */
  5688. LVAL fnodes=NIL;                /* list of free nodes */
  5689.  
  5690. /* vector (and string) space */
  5691. VSEGMENT *vsegments=NULL;       /* list of vector segments */
  5692. VSEGMENT *vscurrent=NULL;       /* current vector segment */
  5693. int vscount=0;                  /* number of vector segments */
  5694. LVAL *vfree=NULL;               /* next free location in vector space */
  5695. LVAL *vtop=NULL;                /* top of vector space */
  5696.  
  5697. /* external variables */
  5698. extern LVAL s_unbound;          /* *UNBOUND* symbol */
  5699. extern LVAL obarray;            /* *OBARRAY* symbol */
  5700. extern LVAL default_object;     /* default object */
  5701. extern LVAL eof_object;         /* eof object */
  5702. extern LVAL true_lval;          /* truth value */
  5703.  
  5704. /* external routines */
  5705. extern unsigned char *calloc();
  5706.  
  5707. /* forward declarations */
  5708. FORWARD LVAL allocnode();
  5709. FORWARD LVAL allocvector();
  5710.  
  5711. /* cons - construct a new cons node */
  5712. LVAL cons(x,y)
  5713.   LVAL x,y;
  5714. {
  5715.     LVAL nnode;
  5716.  
  5717.     /* get a free node */
  5718.     if ((nnode = fnodes) == NIL) {
  5719.         check(2);
  5720.         push(x);
  5721.         push(y);
  5722.         findmemory();
  5723.         if ((nnode = fnodes) == NIL)
  5724.             xlabort("insufficient node space");
  5725.         drop(2);
  5726.     }
  5727.  
  5728.     /* unlink the node from the free list */
  5729.     fnodes = cdr(nnode);
  5730.     --nfree;
  5731.  
  5732.     /* initialize the new node */
  5733.     nnode->n_type = CONS;
  5734.     rplaca(nnode,x);
  5735.     rplacd(nnode,y);
  5736.  
  5737.     /* return the new node */
  5738.     return (nnode);
  5739. }
  5740.  
  5741. /* newframe - create a new environment frame */
  5742. LVAL newframe(parent,size)
  5743.   LVAL parent; int size;
  5744. {
  5745.     LVAL frame;
  5746.     frame = cons(newvector(size),parent);
  5747.     frame->n_type = ENV;
  5748.     return (frame);
  5749. }
  5750.  
  5751. /* cvstring - convert a string to a string node */
  5752. LVAL cvstring(str)
  5753.   unsigned char *str;
  5754. {
  5755.     LVAL val;
  5756.     val = newstring(strlen(str)+1);
  5757.     strcpy(getstring(val),str);
  5758.     return (val);
  5759. }
  5760.  
  5761. /* cvsymbol - convert a string to a symbol */
  5762. LVAL cvsymbol(pname)
  5763.   unsigned char *pname;
  5764. {
  5765.     LVAL val;
  5766.     val = allocvector(SYMBOL,SYMSIZE);
  5767.     cpush(val);
  5768.     setvalue(val,s_unbound);
  5769.     setpname(val,cvstring(pname));
  5770.     setplist(val,NIL);
  5771.     return (pop());
  5772. }
  5773.  
  5774. /* cvfixnum - convert an integer to a fixnum node */
  5775. LVAL cvfixnum(n)
  5776.   FIXTYPE n;
  5777. {
  5778.     LVAL val;
  5779.     if (n >= SFIXMIN && n <= SFIXMAX)
  5780.         return (cvsfixnum(n));
  5781.     val = allocnode(FIXNUM);
  5782.     val->n_int = n;
  5783.     return (val);
  5784. }
  5785.  
  5786. /* cvflonum - convert a floating point number to a flonum node */
  5787. LVAL cvflonum(n)
  5788.   FLOTYPE n;
  5789. {
  5790.     LVAL val;
  5791.     val = allocnode(FLONUM);
  5792.     val->n_flonum = n;
  5793.     return (val);
  5794. }
  5795.  
  5796. /* cvchar - convert an integer to a character node */
  5797. LVAL cvchar(ch)
  5798.   int ch;
  5799. {
  5800.     LVAL val;
  5801.     val = allocnode(CHAR);
  5802.     val->n_chcode = ch;
  5803.     return (val);
  5804. }
  5805.  
  5806. /* cvclosure - convert code and an environment to a closure */
  5807. LVAL cvclosure(code,env)
  5808.   LVAL code,env;
  5809. {
  5810.     LVAL val;
  5811.     val = cons(code,env);
  5812.     val->n_type = CLOSURE;
  5813.     return (val);
  5814. }
  5815.  
  5816. /* cvpromise - convert a procedure to a promise */
  5817. LVAL cvpromise(code,env)
  5818.   LVAL code,env;
  5819. {
  5820.     LVAL val;
  5821.     val = cons(cvclosure(code,env),NIL);
  5822.     val->n_type = PROMISE;
  5823.     return (val);
  5824. }
  5825.  
  5826. /* cvmethod - convert code and an environment to a method */
  5827. LVAL cvmethod(code,class)
  5828.   LVAL code,class;
  5829. {
  5830.     LVAL val;
  5831.     val = cons(code,class);
  5832.     val->n_type = METHOD;
  5833.     return (val);
  5834. }
  5835.  
  5836. /* cvsubr - convert a function to a subr/xsubr */
  5837. LVAL cvsubr(type,fcn,offset)
  5838.   int type; LVAL (*fcn)(); int offset;
  5839. {
  5840.     LVAL val;
  5841.     val = allocnode(type);
  5842.     val->n_subr = fcn;
  5843.     val->n_offset = offset;
  5844.     return (val);
  5845. }
  5846.  
  5847. /* cvport - convert a file pointer to an port */
  5848. LVAL cvport(fp,flags)
  5849.   FILE *fp; int flags;
  5850. {
  5851.     LVAL val;
  5852.     val = allocnode(PORT);
  5853.     setfile(val,fp);
  5854.     setsavech(val,'\0');
  5855.     setpflags(val,flags);
  5856.     return (val);
  5857. }
  5858.  
  5859. /* newvector - allocate and initialize a new vector */
  5860. LVAL newvector(size)
  5861.   int size;
  5862. {
  5863.     return (allocvector(VECTOR,size));
  5864. }
  5865.  
  5866. /* newstring - allocate and initialize a new string */
  5867. LVAL newstring(size)
  5868.   int size;
  5869. {
  5870.     LVAL val;
  5871.     val = allocvector(STRING,btow_size(size));
  5872.     val->n_vsize = size;
  5873.     return (val);
  5874. }
  5875.  
  5876. /* newcode - create a new code object */
  5877. LVAL newcode(nlits)
  5878.   int nlits;
  5879. {
  5880.     return (allocvector(CODE,nlits));
  5881. }
  5882.  
  5883. /* newcontinuation - create a new continuation object */
  5884. LVAL newcontinuation(size)
  5885.   int size;
  5886. {
  5887.     return (allocvector(CONTINUATION,size));
  5888. }
  5889.  
  5890. /* newobject - allocate and initialize a new object */
  5891. LVAL newobject(cls,size)
  5892.   LVAL cls; int size;
  5893. {
  5894.     LVAL val;
  5895.     val = allocvector(OBJECT,size+2); /* class, ivars */
  5896.     setclass(val,cls);
  5897.     return (val);
  5898. }
  5899.  
  5900. /* allocnode - allocate a new node */
  5901. LOCAL LVAL allocnode(type)
  5902.   int type;
  5903. {
  5904.     LVAL nnode;
  5905.  
  5906.     /* get a free node */
  5907.     if ((nnode = fnodes) == NIL) {
  5908.         findmemory();
  5909.         if ((nnode = fnodes) == NIL)
  5910.             xlabort("insufficient node space");
  5911.     }
  5912.  
  5913.     /* unlink the node from the free list */
  5914.     fnodes = cdr(nnode);
  5915.     --nfree;
  5916.  
  5917.     /* initialize the new node */
  5918.     nnode->n_type = type;
  5919.     rplacd(nnode,NIL);
  5920.  
  5921.     /* return the new node */
  5922.     return (nnode);
  5923. }
  5924.  
  5925. /* findmemory - garbage collect, then add more node space if necessary */
  5926. LOCAL findmemory()
  5927. {
  5928.     /* first try garbage collecting */
  5929.     gc();
  5930.  
  5931.     /* expand memory only if less than one segment is free */
  5932.     if (nfree < (long)NSSIZE)
  5933.         nexpand(NSSIZE);
  5934. }
  5935.  
  5936. /* nexpand - expand node space */
  5937. int nexpand(size)
  5938.   int size;
  5939. {
  5940.     NSEGMENT *newnsegment(),*newseg;
  5941.     LVAL p;
  5942.     int i;
  5943.  
  5944.     /* allocate the new segment */
  5945.     if ((newseg = newnsegment(size)) != NULL) {
  5946.  
  5947.         /* add each new node to the free list */
  5948.         p = &newseg->ns_data[0];
  5949.         for (i = NSSIZE; --i >= 0; ++p) {
  5950.             p->n_type = FREE;
  5951.             p->n_flags = 0;
  5952.             rplacd(p,fnodes);
  5953.             fnodes = p;
  5954.         }
  5955.     }
  5956.     return (newseg != NULL);
  5957. }
  5958.  
  5959. /* allocvector - allocate and initialize a new vector node */
  5960. LOCAL LVAL allocvector(type,size)
  5961.   int type,size;
  5962. {
  5963.     register LVAL val,*p;
  5964.     register int i;
  5965.  
  5966.     /* get a free node */
  5967.     if ((val = fnodes) == NIL) {
  5968.         findmemory();
  5969.         if ((val = fnodes) == NIL)
  5970.             xlabort("insufficient node space");
  5971.     }
  5972.  
  5973.     /* unlink the node from the free list */
  5974.     fnodes = cdr(fnodes);
  5975.     --nfree;
  5976.  
  5977.     /* initialize the vector node */
  5978.     val->n_type = type;
  5979.     val->n_vsize = size;
  5980.     val->n_vdata = NULL;
  5981.     cpush(val);
  5982.  
  5983.     /* add space for the backpointer */
  5984.     ++size;
  5985.     
  5986.     /* make sure there's enough space */
  5987.     if (!VCOMPARE(vfree,size,vtop)
  5988.     &&  !checkvmemory(size)
  5989.     &&  !findvmemory(size))
  5990.         xlabort("insufficient vector space");
  5991.  
  5992.     /* allocate the next available block */
  5993.     p = vfree;
  5994.     vfree += size;
  5995.     
  5996.     /* store the backpointer */
  5997.     *p++ = top();
  5998.     val->n_vdata = p;
  5999.  
  6000.     /* set all the elements to NIL */
  6001.     for (i = size; i > 1; --i)
  6002.         *p++ = NIL;
  6003.  
  6004.     /* return the new vector */
  6005.     return (pop());
  6006. }
  6007.  
  6008. /* findvmemory - find vector memory */
  6009. LOCAL int findvmemory(size)
  6010.   int size;
  6011. {
  6012.     /* try garbage collecting */
  6013.     gc();
  6014.  
  6015.     /* check to see if we found enough memory */
  6016.     if (VCOMPARE(vfree,size,vtop) || checkvmemory(size))
  6017.         return (TRUE);
  6018.  
  6019.     /* expand vector space */
  6020.     return (makevmemory(size));
  6021. }
  6022.  
  6023. /* checkvmemory - check for vector memory (used by 'xsimage.c') */
  6024. int checkvmemory(size)
  6025.   int size;
  6026. {
  6027.     VSEGMENT *vseg;
  6028.     for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next)
  6029.         if (vseg != vscurrent && VCOMPARE(vseg->vs_free,size,vseg->vs_top)) {
  6030.             if (vscurrent != NULL)
  6031.                 vscurrent->vs_free = vfree;
  6032.             vfree = vseg->vs_free;
  6033.             vtop = vseg->vs_top;
  6034.             vscurrent = vseg;
  6035.             return (TRUE);
  6036.         }       
  6037.     return (FALSE);
  6038. }
  6039.     
  6040. /* makevmemory - make vector memory (used by 'xsimage.c') */
  6041. int makevmemory(size)
  6042.   int size;
  6043. {
  6044.     return (vexpand(size < VSSIZE ? VSSIZE : size));
  6045. }
  6046.  
  6047. /* vexpand - expand vector space */
  6048. int vexpand(size)
  6049.   int size;
  6050. {
  6051.     VSEGMENT *newvsegment(),*vseg;
  6052.  
  6053.     /* allocate the new segment */
  6054.     if ((vseg = newvsegment(size)) != NULL) {
  6055.  
  6056.         /* initialize the new segment and make it current */
  6057.         if (vscurrent != NULL)
  6058.             vscurrent->vs_free = vfree;
  6059.         vfree = vseg->vs_free;
  6060.         vtop = vseg->vs_top;
  6061.         vscurrent = vseg;
  6062.     }
  6063.     return (vseg != NULL);
  6064. }
  6065.  
  6066. /* newnsegment - create a new node segment */
  6067. NSEGMENT *newnsegment(n)
  6068.   unsigned int n;
  6069. {
  6070.     NSEGMENT *newseg;
  6071.  
  6072.     /* allocate the new segment */
  6073.     if ((newseg = (NSEGMENT *)calloc(1,nsegsize(n))) == NULL)
  6074.         return (NULL);
  6075.  
  6076.     /* initialize the new segment */
  6077.     newseg->ns_size = n;
  6078.     newseg->ns_next = NULL;
  6079.     if (nsegments)
  6080.         nslast->ns_next = newseg;
  6081.     else
  6082.         nsegments = newseg;
  6083.     nslast = newseg;
  6084.  
  6085.     /* update the statistics */
  6086.     total += (long)nsegsize(n);
  6087.     nnodes += (long)n;
  6088.     nfree += (long)n;
  6089.     ++nscount;
  6090.  
  6091.     /* return the new segment */
  6092.     return (newseg);
  6093. }
  6094.  
  6095. /* newvsegment - create a new vector segment */
  6096. VSEGMENT *newvsegment(n)
  6097.   unsigned int n;
  6098. {
  6099.     VSEGMENT *newseg;
  6100.  
  6101.     /* allocate the new segment */
  6102.     if ((newseg = (VSEGMENT *)calloc(1,vsegsize(n))) == NULL)
  6103.         return (NULL);
  6104.  
  6105.     /* initialize the new segment */
  6106.     newseg->vs_free = &newseg->vs_data[0];
  6107.     newseg->vs_top = newseg->vs_free + n;
  6108.     newseg->vs_next = vsegments;
  6109.     vsegments = newseg;
  6110.  
  6111.     /* update the statistics */
  6112.     total += (long)vsegsize(n);
  6113.     ++vscount;
  6114.  
  6115.     /* return the new segment */
  6116.     return (newseg);
  6117. }
  6118.  
  6119. /* gc - garbage collect */
  6120. gc()
  6121. {
  6122.     register LVAL *p,tmp;
  6123.     int compact();
  6124.  
  6125.     /* mark the obarray and the current environment */
  6126.     if (obarray && ispointer(obarray))
  6127.         mark(obarray);
  6128.     if (xlfun && ispointer(xlfun))
  6129.         mark(xlfun);
  6130.     if (xlenv && ispointer(xlenv))
  6131.         mark(xlenv);
  6132.     if (xlval && ispointer(xlval))
  6133.         mark(xlval);
  6134.     if (default_object && ispointer(default_object))
  6135.         mark(default_object);
  6136.     if (eof_object && ispointer(eof_object))
  6137.         mark(eof_object);
  6138.     if (true_lval && ispointer(true_lval))
  6139.         mark(true_lval);
  6140.  
  6141.     /* mark the stack */
  6142.     for (p = xlsp; p < xlstktop; ++p)
  6143.         if ((tmp = *p) && ispointer(tmp))
  6144.             mark(tmp);
  6145.  
  6146.     /* compact vector space */
  6147.     gc_protect(compact);
  6148.  
  6149.     /* sweep memory collecting all unmarked nodes */
  6150.     sweep();
  6151.  
  6152.     /* count the gc call */
  6153.     ++gccalls;
  6154. }
  6155.  
  6156. /* mark - mark all accessible nodes */
  6157. LOCAL mark(ptr)
  6158.   LVAL ptr;
  6159. {
  6160.     register LVAL this,prev,tmp;
  6161.  
  6162.     /* initialize */
  6163.     prev = NIL;
  6164.     this = ptr;
  6165.  
  6166.     /* mark this node */
  6167.     for (;;) {
  6168.  
  6169.         /* descend as far as we can */
  6170.         while (!(this->n_flags & MARK))
  6171.  
  6172.             /* mark this node and trace its children */
  6173.             switch (this->n_type) {
  6174.             case CONS:          /* mark cons-like nodes */
  6175.             case CLOSURE:
  6176.             case METHOD:
  6177.             case PROMISE:
  6178.             case ENV:
  6179.                 this->n_flags |= MARK;
  6180.                 if ((tmp = car(this)) && ispointer(tmp)) {
  6181.                     this->n_flags |= LEFT;
  6182.                     rplaca(this,prev);
  6183.                     prev = this;
  6184.                     this = tmp;
  6185.                 }
  6186.                 else if ((tmp = cdr(this)) && ispointer(tmp)) {
  6187.                     rplacd(this,prev);
  6188.                     prev = this;
  6189.                     this = tmp;
  6190.                 }
  6191.                 break;
  6192.             case SYMBOL:        /* mark vector-like nodes */
  6193.             case OBJECT:
  6194.             case VECTOR:
  6195.             case CODE:
  6196.             case CONTINUATION:
  6197.                 this->n_flags |= MARK;
  6198.                 markvector(this);
  6199.                 break;
  6200.             case FIXNUM:        /* mark objects that don't contain pointers */
  6201.             case FLONUM:
  6202.             case STRING:
  6203.             case PORT:
  6204.             case SUBR:
  6205.             case XSUBR:
  6206.             case CSUBR:
  6207.             case CHAR:
  6208.                 this->n_flags |= MARK;
  6209.                 break;
  6210.             default:            /* bad object type */
  6211.                 xlfatal("bad object type %d\n",this->n_type);
  6212.                 break;
  6213.             }
  6214.  
  6215.         /* backup to a point where we can continue descending */
  6216.         for (;;)
  6217.  
  6218.             /* make sure there is a previous node */
  6219.             if (prev) {
  6220.                 if (prev->n_flags & LEFT) {     /* came from left side */
  6221.                     prev->n_flags &= ~LEFT;
  6222.                     tmp = car(prev);
  6223.                     rplaca(prev,this);
  6224.                     if ((this = cdr(prev)) && ispointer(this)) {
  6225.                         rplacd(prev,tmp);                       
  6226.                         break;
  6227.                     }
  6228.                 }
  6229.                 else {                          /* came from right side */
  6230.                     tmp = cdr(prev);
  6231.                     rplacd(prev,this);
  6232.                 }
  6233.                 this = prev;                    /* step back up the branch */
  6234.                 prev = tmp;
  6235.             }
  6236.  
  6237.             /* no previous node, must be done */
  6238.             else
  6239.                 return;
  6240.     }
  6241. }
  6242.  
  6243. /* markvector - mark a vector-like node */
  6244. LOCAL markvector(vect)
  6245.   LVAL vect;
  6246. {
  6247.     register LVAL tmp,*p;
  6248.     register int n;
  6249.     if (p = vect->n_vdata) {
  6250.         n = getsize(vect);
  6251.         while (--n >= 0)
  6252.             if ((tmp = *p++) && ispointer(tmp))
  6253.                 mark(tmp);
  6254.     }
  6255. }
  6256.  
  6257. /* compact - compact vector space */
  6258. LOCAL compact()
  6259. {
  6260.     VSEGMENT *vseg;
  6261.  
  6262.     /* store the current segment information */
  6263.     if (vscurrent)
  6264.         vscurrent->vs_free = vfree;
  6265.  
  6266.     /* compact each vector segment */
  6267.     for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next)
  6268.         compact_vector(vseg);
  6269.  
  6270.     /* make the first vector segment current */
  6271.     if (vscurrent = vsegments) {
  6272.         vfree = vscurrent->vs_free;
  6273.         vtop = vscurrent->vs_top;
  6274.     }
  6275. }
  6276.  
  6277. /* compact_vector - compact a vector segment */
  6278. LOCAL compact_vector(vseg)
  6279.   VSEGMENT *vseg;
  6280. {
  6281.     register LVAL *vdata,*vnext,*vfree,vector;
  6282.     register int vsize;
  6283.  
  6284.     vdata = vnext = &vseg->vs_data[0];
  6285.     vfree = vseg->vs_free;
  6286.     while (vdata < vfree) {
  6287.         vector = *vdata;
  6288.         vsize = (vector->n_type == STRING ? btow_size(vector->n_vsize)
  6289.                                           : vector->n_vsize) + 1;
  6290.         if (vector->n_flags & MARK) {
  6291.             if (vdata == vnext) {
  6292.                 vdata += vsize;
  6293.                 vnext += vsize;
  6294.             }
  6295.             else {
  6296.                 vector->n_vdata = vnext + 1;
  6297.                 while (--vsize >= 0)
  6298.                     *vnext++ = *vdata++;
  6299.             }
  6300.         }
  6301.         else
  6302.             vdata += vsize;
  6303.     }
  6304.     vseg->vs_free = vnext;
  6305. }
  6306.  
  6307. /* sweep - sweep all unmarked nodes and add them to the free list */
  6308. LOCAL sweep()
  6309. {
  6310.     NSEGMENT *nseg;
  6311.  
  6312.     /* empty the free list */
  6313.     fnodes = NIL;
  6314.     nfree = 0L;
  6315.  
  6316.     /* sweep each node segment */
  6317.     for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next)
  6318.         sweep_segment(nseg);
  6319. }
  6320.  
  6321. /* sweep_segment - sweep a node segment */
  6322. LOCAL sweep_segment(nseg)
  6323.   NSEGMENT *nseg;
  6324. {
  6325.     register FIXTYPE n;
  6326.     register LVAL p;
  6327.  
  6328.     /* add all unmarked nodes */
  6329.     for (p = &nseg->ns_data[0], n = nseg->ns_size; --n >= 0L; ++p)
  6330.         if (!(p->n_flags & MARK)) {
  6331.             switch (p->n_type) {
  6332.             case PORT:
  6333.                 if (getfile(p))
  6334.                     osclose(getfile(p));
  6335.                 break;
  6336.             }
  6337.             p->n_type = FREE;
  6338.             rplacd(p,fnodes);
  6339.             fnodes = p;
  6340.             ++nfree;
  6341.         }
  6342.         else
  6343.             p->n_flags &= ~MARK;
  6344. }
  6345.  
  6346. /* xlminit - initialize the dynamic memory module */
  6347. xlminit(ssize)
  6348.   unsigned int ssize;
  6349. {
  6350.     unsigned int n;
  6351.  
  6352.     /* initialize our internal variables */
  6353.     gccalls = 0;
  6354.     total = 0L;
  6355.  
  6356.     /* initialize node space */
  6357.     nsegments = nslast = NULL;
  6358.     nscount = 0;
  6359.     nnodes = nfree = 0L;
  6360.     fnodes = NIL;
  6361.  
  6362.     /* initialize vector space */
  6363.     vsegments = vscurrent = NULL;
  6364.     vscount = 0;
  6365.     vfree = vtop = NULL;
  6366.     
  6367.     /* allocate the value stack */
  6368.     n = ssize * sizeof(LVAL);
  6369.     if ((xlstkbase = (LVAL *)calloc(1,n)) == NULL)
  6370.         xlfatal("insufficient memory");
  6371.     total += (long)n;
  6372.  
  6373.     /* initialize structures that are marked by the collector */
  6374.     obarray = default_object = eof_object = true_lval = NIL;
  6375.     xlfun = xlenv = xlval = NIL;
  6376.  
  6377.     /* initialize the stack */
  6378.     xlsp = xlstktop = xlstkbase + ssize;
  6379. }
  6380. itialize vector space */
  6381.     vsegments = vscurrent = NULL;
  6382.     vscount = 0;
  6383.     vfree = vtop = NULL;
  6384.     
  6385.     /* allocate the value stack */
  6386.     n = ssize * sizeof(LVAL);
  6387.     if ((xlstkbase = (LVAL *)calloc(1,n)) ==src/xsftab.c
  6388.  
  6389.  
  6390.  
  6391. /*      Copyright (c) 1988, by David Michael Betz
  6392.         All Rights Reserved
  6393.         Permission is granted for unrestricted non-commercial use       */
  6394.  
  6395. #include "xscheme.h"
  6396.  
  6397. /* external variables */
  6398. extern LVAL s_stdin,s_stdout;
  6399.  
  6400. /* external functions */
  6401. extern LVAL
  6402.     xapply(),xcallcc(),xmap(),xmap1(),xforeach(),xforeach1(),
  6403.     xforce(),xforce1(),xcallwi(),xcallwo(),xwithfile1(),
  6404.     xload(),xloadnoisily(),xload1(),
  6405.     xsendsuper(),clnew(),clisnew(),clanswer(),
  6406.     obisnew(),obclass(),obshow(),
  6407.     xcons(),xcar(),xcdr(),
  6408.     xcaar(),xcadr(),xcdar(),xcddr(),
  6409.     xcaaar(),xcaadr(),xcadar(),xcaddr(),
  6410.     xcdaar(),xcdadr(),xcddar(),xcdddr(),
  6411.     xcaaaar(),xcaaadr(),xcaadar(),xcaaddr(),
  6412.     xcadaar(),xcadadr(),xcaddar(),xcadddr(),
  6413.     xcdaaar(),xcdaadr(),xcdadar(),xcdaddr(),
  6414.     xcddaar(),xcddadr(),xcdddar(),xcddddr(),
  6415.     xsetcar(),xsetcdr(),xlist(),xliststar(),
  6416.     xappend(),xreverse(),xlastpair(),xlength(),xlistref(),xlisttail(),
  6417.     xmember(),xmemv(),xmemq(),xassoc(),xassv(),xassq(),
  6418.     xsymvalue(),xsetsymvalue(),xsymplist(),xsetsymplist(),xgensym(),
  6419.     xboundp(),xget(),xput(),
  6420.     xtheenvironment(),xprocenvironment(),xenvp(),xenvbindings(),xenvparent(),
  6421.     xvector(),xmakevector(),xvlength(),xvref(),xvset(),
  6422.     xvectlist(),xlistvect(),
  6423.     xmakearray(),xaref(),xaset(),
  6424.     xsymstr(),xstrsym(),
  6425.     xnull(),xatom(),xlistp(),xnumberp(),xbooleanp(),
  6426.     xpairp(),xsymbolp(),xintegerp(),xrealp(),xcharp(),xstringp(),xvectorp(),
  6427.     xprocedurep(),xobjectp(),xdefaultobjectp(),
  6428.     xinputportp(),xoutputportp(),xportp(),
  6429.     xeq(),xeqv(),xequal(),
  6430.     xzerop(),xpositivep(),xnegativep(),xoddp(),xevenp(),
  6431.     xexactp(),xinexactp(),
  6432.     xadd1(),xsub1(),xabs(),xgcd(),xrandom(),
  6433.     xadd(),xsub(),xmul(),xdiv(),xquo(),xrem(),xmin(),xmax(),
  6434.     xsin(),xcos(),xtan(),xasin(),xacos(),xatan(),
  6435.     xxexp(),xsqrt(),xexpt(),xxlog(),xtruncate(),xfloor(),xceiling(),xround(),
  6436.     xlogand(),xlogior(),xlogxor(),xlognot(),
  6437.     xlss(),xleq(),xeql(),xgeq(),xgtr(),
  6438.     xstrlen(),xstrnullp(),xstrappend(),xstrref(),xsubstring(),
  6439.     xstrlist(),xliststring(),
  6440.     xstrlss(),xstrleq(),xstreql(),xstrgeq(),xstrgtr(),
  6441.     xstrilss(),xstrileq(),xstrieql(),xstrigeq(),xstrigtr(),
  6442.     xcharint(),xintchar(),
  6443.     xchrlss(),xchrleq(),xchreql(),xchrgeq(),xchrgtr(),
  6444.     xchrilss(),xchrileq(),xchrieql(),xchrigeq(),xchrigtr(),
  6445.     xread(),xrdchar(),xrdbyte(),xrdshort(),xrdlong(),xeofobjectp(),
  6446.     xwrite(),xwrchar(),xwrbyte(),xwrshort(),xwrlong(),
  6447.     xdisplay(),xnewline(),xprint(),xprbreadth(),xprdepth(),
  6448.     xopeni(),xopeno(),xopena(),xopenu(),xclosei(),xcloseo(),xclose(),
  6449.     xgetfposition(),xsetfposition(),xcurinput(),xcuroutput(),
  6450.     xtranson(),xtransoff(),xgetarg(),xexit(),xcompile(),xdecompile(),xgc(),
  6451.     xsave(),xrestore(),xtraceon(),xtraceoff(),xreset(),xerror(),
  6452.     xicar(),xicdr(),xisetcar(),xisetcdr(),xivlength(),xivref(),xivset();
  6453.  
  6454. /* include machine specific declarations */
  6455. #include "osdefs.h"
  6456.  
  6457. int xsubrcnt = 12;      /* number of XSUBR functions */
  6458. int csubrcnt = 17;      /* number of CSUBR functions + xsubrcnt */
  6459.  
  6460. /* built-in functions */
  6461. FUNDEF funtab[] = {
  6462.  
  6463.         /* functions that call eval or apply (# must match xsubrcnt) */
  6464. {       "APPLY",                                xapply          },
  6465. {       "CALL-WITH-CURRENT-CONTINUATION",       xcallcc         },
  6466. {       "CALL/CC",                              xcallcc         },
  6467. {       "MAP",                                  xmap            },
  6468. {       "FOR-EACH",                             xforeach        },
  6469. {       "CALL-WITH-INPUT-FILE",                 xcallwi         },
  6470. {       "CALL-WITH-OUTPUT-FILE",                xcallwo         },
  6471. {       "LOAD",                                 xload           },
  6472. {       "LOAD-NOISILY",                         xloadnoisily    },
  6473. {       "SEND-SUPER",                           xsendsuper      },
  6474. {       "%CLASS-NEW",                           clnew           },
  6475. {       "FORCE",                                xforce          },
  6476.  
  6477.         /* continuations for xsubrs (# must match csubrcnt) */
  6478. {       "%MAP1",                                xmap1           },
  6479. {       "%FOR-EACH1",                           xforeach1       },
  6480. {       "%WITH-FILE1",                          xwithfile1      },
  6481. {       "%LOAD1",                               xload1          },
  6482. {       "%FORCE1",                              xforce1         },
  6483.  
  6484.         /* methods */
  6485. {       "%CLASS-ISNEW",                         clisnew         },
  6486. {       "%CLASS-ANSWER",                        clanswer        },
  6487. {       "%OBJECT-ISNEW",                        obisnew         },
  6488. {       "%OBJECT-CLASS",                        obclass         },
  6489. {       "%OBJECT-SHOW",                         obshow          },
  6490.  
  6491.         /* list functions */
  6492. {       "CONS",                                 xcons           },
  6493. {       "CAR",                                  xcar            },
  6494. {       "CDR",                                  xcdr            },
  6495. {       "CAAR",                                 xcaar           },
  6496. {       "CADR",                                 xcadr           },
  6497. {       "CDAR",                                 xcdar           },
  6498. {       "CDDR",                                 xcddr           },
  6499. {       "CAAAR",                                xcaaar          },
  6500. {       "CAADR",                                xcaadr          },
  6501. {       "CADAR",                                xcadar          },
  6502. {       "CADDR",                                xcaddr          },
  6503. {       "CDAAR",                                xcdaar          },
  6504. {       "CDADR",                                xcdadr          },
  6505. {       "CDDAR",                                xcddar          },
  6506. {       "CDDDR",                                xcdddr          },
  6507. {       "CAAAAR",                               xcaaaar         },
  6508. {       "CAAADR",                               xcaaadr         },
  6509. {       "CAADAR",                               xcaadar         },
  6510. {       "CAADDR",                               xcaaddr         },
  6511. {       "CADAAR",                               xcadaar         },
  6512. {       "CADADR",                               xcadadr         },
  6513. {       "CADDAR",                               xcaddar         },
  6514. {       "CADDDR",                               xcadddr         },
  6515. {       "CDAAAR",                               xcdaaar         },
  6516. {       "CDAADR",                               xcdaadr         },
  6517. {       "CDADAR",                               xcdadar         },
  6518. {       "CDADDR",                               xcdaddr         },
  6519. {       "CDDAAR",                               xcddaar         },
  6520. {       "CDDADR",                               xcddadr         },
  6521. {       "CDDDAR",                               xcdddar         },
  6522. {       "CDDDDR",                               xcddddr         },
  6523. {       "LIST",                                 xlist           },
  6524. {       "LIST*",                                xliststar       },
  6525. {       "APPEND",                               xappend         },
  6526. {       "REVERSE",                              xreverse        },
  6527. {       "LAST-PAIR",                            xlastpair       },
  6528. {       "LENGTH",                               xlength         },
  6529. {       "MEMBER",                               xmember         },
  6530. {       "MEMV",                                 xmemv           },
  6531. {       "MEMQ",                                 xmemq           },
  6532. {       "ASSOC",                                xassoc          },
  6533. {       "ASSV",                                 xassv           },
  6534. {       "ASSQ",                                 xassq           },
  6535. {       "LIST-REF",                             xlistref        },
  6536. {       "LIST-TAIL",                            xlisttail       },
  6537.  
  6538.         /* destructive list functions */
  6539. {       "SET-CAR!",                             xsetcar         },
  6540. {       "SET-CDR!",                             xsetcdr         },
  6541.  
  6542.  
  6543.         /* symbol functions */
  6544. {       "BOUND?",                               xboundp         },
  6545. {       "SYMBOL-VALUE",                         xsymvalue       },
  6546. {       "SET-SYMBOL-VALUE!",                    xsetsymvalue    },
  6547. {       "SYMBOL-PLIST",                         xsymplist       },
  6548. {       "SET-SYMBOL-PLIST!",                    xsetsymplist    },
  6549. {       "GENSYM",                               xgensym         },
  6550. {       "GET",                                  xget            },
  6551. {       "PUT",                                  xput            },
  6552.  
  6553.         /* environment functions */
  6554. {       "THE-ENVIRONMENT",                      xtheenvironment },
  6555. {       "PROCEDURE-ENVIRONMENT",                xprocenvironment},
  6556. {       "ENVIRONMENT?",                         xenvp           },
  6557. {       "ENVIRONMENT-BINDINGS",                 xenvbindings    },
  6558. {       "ENVIRONMENT-PARENT",                   xenvparent      },
  6559.  
  6560.         /* vector functions */
  6561. {       "VECTOR",                               xvector         },
  6562. {       "MAKE-VECTOR",                          xmakevector     },
  6563. {       "VECTOR-LENGTH",                        xvlength        },
  6564. {       "VECTOR-REF",                           xvref           },
  6565. {       "VECTOR-SET!",                          xvset           },
  6566.  
  6567.         /* array functions */
  6568. {       "MAKE-ARRAY",                           xmakearray      },
  6569. {       "ARRAY-REF",                            xaref           },
  6570. {       "ARRAY-SET!",                           xaset           },
  6571.  
  6572.         /* conversion functions */
  6573. {       "SYMBOL->STRING",                       xsymstr         },
  6574. {       "STRING->SYMBOL",                       xstrsym         },
  6575. {       "VECTOR->LIST",                         xvectlist       },
  6576. {       "LIST->VECTOR",                         xlistvect       },
  6577. {       "STRING->LIST",                         xstrlist        },
  6578. {       "LIST->STRING",                         xliststring     },
  6579. {       "CHAR->INTEGER",                        xcharint        },
  6580. {       "INTEGER->CHAR",                        xintchar        },
  6581.  
  6582.         /* predicate functions */
  6583. {       "NULL?",                                xnull           },
  6584. {       "ATOM?",                                xatom           },
  6585. {       "LIST?",                                xlistp          },
  6586. {       "NUMBER?",                              xnumberp        },
  6587. {       "BOOLEAN?",                             xbooleanp       },
  6588. {       "PAIR?",                                xpairp          },
  6589. {       "SYMBOL?",                              xsymbolp        },
  6590. {       "COMPLEX?",                             xrealp          }, /*(1)*/
  6591. {       "REAL?",                                xrealp          },
  6592. {       "RATIONAL?",                            xintegerp       }, /*(1)*/
  6593. {       "INTEGER?",                             xintegerp       },
  6594. {       "CHAR?",                                xcharp          },
  6595. {       "STRING?",                              xstringp        },
  6596. {       "VECTOR?",                              xvectorp        },
  6597. {       "PROCEDURE?",                           xprocedurep     },
  6598. {       "PORT?",                                xportp          },
  6599. {       "INPUT-PORT?",                          xinputportp     },
  6600. {       "OUTPUT-PORT?",                         xoutputportp    },
  6601. {       "OBJECT?",                              xobjectp        },
  6602. {       "EOF-OBJECT?",                          xeofobjectp     },
  6603. {       "DEFAULT-OBJECT?",                      xdefaultobjectp },
  6604. {       "EQ?",                                  xeq             },
  6605. {       "EQV?",                                 xeqv            },
  6606. {       "EQUAL?",                               xequal          },
  6607.  
  6608.         /* arithmetic functions */
  6609. {       "ZERO?",                                xzerop          },
  6610. {       "POSITIVE?",                            xpositivep      },
  6611. {       "NEGATIVE?",                            xnegativep      },
  6612. {       "ODD?",                                 xoddp           },
  6613. {       "EVEN?",                                xevenp          },
  6614. {       "EXACT?",                               xexactp         },
  6615. {       "INEXACT?",                             xinexactp       },
  6616. {       "TRUNCATE",                             xtruncate       },
  6617. {       "FLOOR",                                xfloor          },
  6618. {       "CEILING",                              xceiling        },
  6619. {       "ROUND",                                xround          },
  6620. {       "1+",                                   xadd1           },
  6621. {       "-1+",                                  xsub1           },
  6622. {       "ABS",                                  xabs            },
  6623. {       "GCD",                                  xgcd            },
  6624. {       "RANDOM",                               xrandom         },
  6625. {       "+",                                    xadd            },
  6626. {       "-",                                    xsub            },
  6627. {       "*",                                    xmul            },
  6628. {       "/",                                    xdiv            },
  6629. {       "QUOTIENT",                             xquo            },
  6630. {       "REMAINDER",                            xrem            },
  6631. {       "MIN",                                  xmin            },
  6632. {       "MAX",                                  xmax            },
  6633. {       "SIN",                                  xsin            },
  6634. {       "COS",                                  xcos            },
  6635. {       "TAN",                                  xtan            },
  6636. {       "ASIN",                                 xasin           },
  6637. {       "ACOS",                                 xacos           },
  6638. {       "ATAN",                                 xatan           },
  6639. {       "EXP",                                  xxexp           },
  6640. {       "SQRT",                                 xsqrt           },
  6641. {       "EXPT",                                 xexpt           },
  6642. {       "LOG",                                  xxlog           },
  6643.  
  6644.         /* bitwise logical functions */
  6645. {       "LOGAND",                               xlogand         },
  6646. {       "LOGIOR",                               xlogior         },
  6647. {       "LOGXOR",                               xlogxor         },
  6648. {       "LOGNOT",                               xlognot         },
  6649.  
  6650.         /* numeric comparison functions */
  6651. {       "<",                                    xlss            },
  6652. {       "<=",                                   xleq            },
  6653. {       "=",                                    xeql            },
  6654. {       ">=",                                   xgeq            },
  6655. {       ">",                                    xgtr            },
  6656.  
  6657.         /* string functions */
  6658. {       "STRING-LENGTH",                        xstrlen         },
  6659. {       "STRING-NULL?",                         xstrnullp       },
  6660. {       "STRING-APPEND",                        xstrappend      },
  6661. {       "STRING-REF",                           xstrref         },
  6662. {       "SUBSTRING",                            xsubstring      },
  6663. {       "STRING<?",                             xstrlss         },
  6664. {       "STRING<=?",                            xstrleq         },
  6665. {       "STRING=?",                             xstreql         },
  6666. {       "STRING>=?",                            xstrgeq         },
  6667. {       "STRING>?",                             xstrgtr         },
  6668. {       "STRING-CI<?",                          xstrilss        },
  6669. {       "STRING-CI<=?",                         xstrileq        },
  6670. {       "STRING-CI=?",                          xstrieql        },
  6671. {       "STRING-CI>=?",                         xstrigeq        },
  6672. {       "STRING-CI>?",                          xstrigtr        },
  6673.  
  6674.         /* character functions */
  6675. {       "CHAR<?",                               xchrlss         },
  6676. {       "CHAR<=?",                              xchrleq         },
  6677. {       "CHAR=?",                               xchreql         },
  6678. {       "CHAR>=?",                              xchrgeq         },
  6679. {       "CHAR>?",                               xchrgtr         },
  6680. {       "CHAR-CI<?",                            xchrilss        },
  6681. {       "CHAR-CI<=?",                           xchrileq        },
  6682. {       "CHAR-CI=?",                            xchrieql        },
  6683. {       "CHAR-CI>=?",                           xchrigeq        },
  6684. {       "CHAR-CI>?",                            xchrigtr        },
  6685.  
  6686.         /* I/O functions */
  6687. {       "READ",                                 xread           },
  6688. {       "READ-CHAR",                            xrdchar         },
  6689. {       "READ-BYTE",                            xrdbyte         },
  6690. {       "READ-SHORT",                           xrdshort        },
  6691. {       "READ-LONG",                            xrdlong         },
  6692. {       "WRITE",                                xwrite          },
  6693. {       "WRITE-CHAR",                           xwrchar         },
  6694. {       "WRITE-BYTE",                           xwrbyte         },
  6695. {       "WRITE-SHORT",                          xwrshort        },
  6696. {       "WRITE-LONG",                           xwrlong         },
  6697. {       "DISPLAY",                              xdisplay        },
  6698. {       "PRINT",                                xprint          },
  6699. {       "NEWLINE",                              xnewline        },
  6700.  
  6701.         /* print control functions */
  6702. {       "PRINT-BREADTH",                        xprbreadth      },
  6703. {       "PRINT-DEPTH",                          xprdepth        },
  6704.  
  6705.         /* file I/O functions */
  6706. {       "OPEN-INPUT-FILE",                      xopeni          },
  6707. {       "OPEN-OUTPUT-FILE",                     xopeno          },
  6708. {       "OPEN-APPEND-FILE",                     xopena          },
  6709. {       "OPEN-UPDATE-FILE",                     xopenu          },
  6710. {       "CLOSE-PORT",                           xclose          },
  6711. {       "CLOSE-INPUT-PORT",                     xclosei         },
  6712. {       "CLOSE-OUTPUT-PORT",                    xcloseo         },
  6713. {       "GET-FILE-POSITION",                    xgetfposition   },
  6714. {       "SET-FILE-POSITION!",                   xsetfposition   },
  6715. {       "CURRENT-INPUT-PORT",                   xcurinput       },
  6716. {       "CURRENT-OUTPUT-PORT",                  xcuroutput      },
  6717.  
  6718.         /* utility functions */
  6719. {       "TRANSCRIPT-ON",                        xtranson        },
  6720. {       "TRANSCRIPT-OFF",                       xtransoff       },
  6721. {       "GETARG",                               xgetarg         },
  6722. {       "EXIT",                                 xexit           },
  6723. {       "COMPILE",                              xcompile        },
  6724. {       "DECOMPILE",                            xdecompile      },
  6725. {       "GC",                                   xgc             },
  6726. {       "SAVE",                                 xsave           },
  6727. {       "RESTORE",                              xrestore        },
  6728. {       "RESET",                                xreset          },
  6729. {       "ERROR",                                xerror          },
  6730.  
  6731.         /* debugging functions */
  6732. {       "TRACE-ON",                             xtraceon        },
  6733. {       "TRACE-OFF",                            xtraceoff       },
  6734.  
  6735.         /* internal functions */
  6736. {       "%CAR",                                 xicar           },
  6737. {       "%CDR",                                 xicdr           },
  6738. {       "%SET-CAR!",                            xisetcar        },
  6739. {       "%SET-CDR!",                            xisetcdr        },
  6740. {       "%VECTOR-LENGTH",                       xivlength       },
  6741. {       "%VECTOR-REF",                          xivref          },
  6742. {       "%VECTOR-SET!",                         xivset          },
  6743.  
  6744. /* include machine specific table entries */
  6745. #include "osptrs.h"
  6746.  
  6747. {0,0} /* end of table marker */
  6748.  
  6749. };
  6750.  
  6751. /* Notes:
  6752.  
  6753.    (1)  This version only supports integers and reals.
  6754.  
  6755. */
  6756.  
  6757. /* curinput - get the current input port */
  6758. LVAL curinput()
  6759. {
  6760.     return (getvalue(s_stdin));
  6761. }
  6762.  
  6763. /* curoutput - get the current output port */
  6764. LVAL curoutput()
  6765. {
  6766.     return (getvalue(s_stdout));
  6767. }
  6768.  
  6769. /* eq - internal 'eq?' function */
  6770. int eq(arg1,arg2)
  6771.   LVAL arg
  6772.